<?php

declare(strict_types=1);

namespace App\Support;

use App\Business\Settlement\Enums\SettlementWriteOffStatus;
use App\Filament\Resources\DberpCustomerReceivables\DberpCustomerReceivableResource;
use App\Filament\Resources\DberpCustomerSettlementQueries\DberpCustomerSettlementQueryResource;
use App\Filament\Resources\DberpPaymentOrders\DberpPaymentOrderResource;
use App\Filament\Resources\DberpReceiptOrders\DberpReceiptOrderResource;
use App\Filament\Resources\DberpReceiptPaymentQueries\DberpReceiptPaymentQueryResource;
use App\Filament\Resources\DberpSettlementStatements\DberpSettlementStatementResource;
use App\Filament\Resources\DberpSettlementWriteOffs\DberpSettlementWriteOffResource;
use App\Filament\Resources\DberpSupplierPayables\DberpSupplierPayableResource;
use App\Filament\Resources\DberpSupplierSettlementQueries\DberpSupplierSettlementQueryResource;

final class DberpSettlementEntryFilamentSupport
{
    /**
     * @param  array<string, mixed>  $state
     * @return array<string, mixed>
     */
    public static function buildCustomerTableFiltersFromAnalysisState(array $state): array
    {
        $filters = self::businessTimeTableFiltersFromAnalysisState($state);

        if (! empty($state['customer_id'])) {
            $filters['customer_id'] = ['value' => (int) $state['customer_id']];
        }

        return $filters;
    }

    /**
     * @param  array<string, mixed>  $state
     * @return array<string, mixed>
     */
    public static function buildSupplierTableFiltersFromAnalysisState(array $state): array
    {
        $filters = self::businessTimeTableFiltersFromAnalysisState($state);

        if (! empty($state['supplier_id'])) {
            $filters['supplier_id'] = ['value' => (int) $state['supplier_id']];
        }

        return $filters;
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function customerIndexUrl(?array $tableFilters = null): string
    {
        return DberpFilamentListPageUrl::append(
            DberpCustomerSettlementQueryResource::getUrl('index'),
            $tableFilters ?? [],
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function supplierIndexUrl(?array $tableFilters = null): string
    {
        return DberpFilamentListPageUrl::append(
            DberpSupplierSettlementQueryResource::getUrl('index'),
            $tableFilters ?? [],
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function customerReceivablesUrl(?array $tableFilters): string
    {
        $filters = [];

        $customerId = self::pickTableFilterValue($tableFilters, 'customer_id');
        if ($customerId !== null) {
            $filters['customer_id'] = ['value' => (int) $customerId];
        }

        return DberpFilamentListPageUrl::append(
            DberpCustomerReceivableResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function supplierPayablesUrl(?array $tableFilters): string
    {
        $filters = [];

        $supplierId = self::pickTableFilterValue($tableFilters, 'supplier_id');
        if ($supplierId !== null) {
            $filters['supplier_id'] = ['value' => (int) $supplierId];
        }

        return DberpFilamentListPageUrl::append(
            DberpSupplierPayableResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function receiptPaymentQueryUrl(?array $tableFilters, string $direction): string
    {
        $filters = [
            'direction' => ['value' => $direction],
        ];

        $counterpartyKey = $direction === 'receipt' ? 'customer_id' : 'supplier_id';
        $counterpartyId = self::pickTableFilterValue($tableFilters, $counterpartyKey);
        if ($counterpartyId !== null) {
            $filters[$counterpartyKey] = ['value' => (int) $counterpartyId];
        }

        $businessTime = self::businessTimeTableFiltersFromTableState($tableFilters);
        if ($businessTime !== []) {
            $filters['business_time'] = $businessTime;
        }

        return DberpFilamentListPageUrl::append(
            DberpReceiptPaymentQueryResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function receiptOrdersUrlFromReceiptPaymentTableFilters(?array $tableFilters): string
    {
        return DberpFilamentListPageUrl::append(
            DberpReceiptOrderResource::getUrl('index'),
            self::receiptOrderTableFiltersFromReceiptPaymentTableFilters($tableFilters),
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function paymentOrdersUrlFromReceiptPaymentTableFilters(?array $tableFilters): string
    {
        return DberpFilamentListPageUrl::append(
            DberpPaymentOrderResource::getUrl('index'),
            self::paymentOrderTableFiltersFromReceiptPaymentTableFilters($tableFilters),
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function customerReceivablesUrlFromReceiptPaymentTableFilters(?array $tableFilters): string
    {
        $filters = [];
        $customerId = self::pickTableFilterValue($tableFilters, 'customer_id');
        if ($customerId !== null) {
            $filters['customer_id'] = ['value' => (int) $customerId];
        }

        return DberpFilamentListPageUrl::append(
            DberpCustomerReceivableResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function supplierPayablesUrlFromReceiptPaymentTableFilters(?array $tableFilters): string
    {
        $filters = [];
        $supplierId = self::pickTableFilterValue($tableFilters, 'supplier_id');
        if ($supplierId !== null) {
            $filters['supplier_id'] = ['value' => (int) $supplierId];
        }

        return DberpFilamentListPageUrl::append(
            DberpSupplierPayableResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     * @return array<string, mixed>
     */
    private static function receiptOrderTableFiltersFromReceiptPaymentTableFilters(?array $tableFilters): array
    {
        $filters = [];

        $customerId = self::pickTableFilterValue($tableFilters, 'customer_id');
        if ($customerId !== null) {
            $filters['customer_id'] = ['value' => (int) $customerId];
        }

        $status = self::pickTableFilterValue($tableFilters, 'status');
        if ($status !== null && $status !== '') {
            $filters['status'] = ['value' => $status];
        }

        $handlerId = self::pickTableFilterValue($tableFilters, 'handler_employee_id');
        if ($handlerId !== null) {
            $filters['handler_employee_id'] = ['value' => (int) $handlerId];
        }

        $businessTime = self::businessTimeTableFiltersFromTableState($tableFilters);
        if ($businessTime !== []) {
            $filters['business_time_range'] = $businessTime;
        }

        return $filters;
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     * @return array<string, mixed>
     */
    private static function paymentOrderTableFiltersFromReceiptPaymentTableFilters(?array $tableFilters): array
    {
        $filters = [];

        $supplierId = self::pickTableFilterValue($tableFilters, 'supplier_id');
        if ($supplierId !== null) {
            $filters['supplier_id'] = ['value' => (int) $supplierId];
        }

        $status = self::pickTableFilterValue($tableFilters, 'status');
        if ($status !== null && $status !== '') {
            $filters['status'] = ['value' => $status];
        }

        $handlerId = self::pickTableFilterValue($tableFilters, 'handler_employee_id');
        if ($handlerId !== null) {
            $filters['handler_employee_id'] = ['value' => (int) $handlerId];
        }

        $businessTime = self::businessTimeTableFiltersFromTableState($tableFilters);
        if ($businessTime !== []) {
            $filters['business_time_range'] = $businessTime;
        }

        return $filters;
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function settlementWriteOffsUrl(?array $tableFilters, string $settlementSide): string
    {
        $filters = [
            'settlement_side' => ['value' => $settlementSide],
            'write_off_status' => ['value' => SettlementWriteOffStatus::Confirmed->value],
        ];

        return DberpFilamentListPageUrl::append(
            DberpSettlementWriteOffResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    public static function settlementStatementsUrl(?array $tableFilters, string $settlementSide): string
    {
        $filters = [
            'settlement_side' => ['value' => $settlementSide],
        ];

        $businessTime = self::businessTimeTableFiltersFromTableState($tableFilters);
        if ($businessTime !== []) {
            $filters['statement_period'] = $businessTime;
        }

        return DberpFilamentListPageUrl::append(
            DberpSettlementStatementResource::getUrl('index'),
            $filters,
        );
    }

    /**
     * @param  array<string, mixed>  $state
     * @return array<string, mixed>
     */
    private static function businessTimeTableFiltersFromAnalysisState(array $state): array
    {
        if (empty($state['business_time_from']) && empty($state['business_time_until'])) {
            return [];
        }

        return [
            'business_time' => array_filter([
                'from' => $state['business_time_from'] ?? null,
                'until' => $state['business_time_until'] ?? null,
            ]),
        ];
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     * @return array{from?: string, until?: string}
     */
    private static function businessTimeTableFiltersFromTableState(?array $tableFilters): array
    {
        if ($tableFilters === null || $tableFilters === []) {
            return [];
        }

        $businessTime = $tableFilters['business_time'] ?? null;

        if (! is_array($businessTime)) {
            return [];
        }

        return array_filter([
            'from' => $businessTime['from'] ?? null,
            'until' => $businessTime['until'] ?? null,
        ]);
    }

    /**
     * @param  array<string, mixed>|null  $tableFilters
     */
    private static function pickTableFilterValue(?array $tableFilters, string $key): mixed
    {
        if ($tableFilters === null || $tableFilters === []) {
            return null;
        }

        $nested = $tableFilters[$key] ?? null;

        if (is_array($nested)) {
            return $nested['value'] ?? null;
        }

        return $tableFilters[$key] ?? null;
    }
}
