<?php

declare(strict_types=1);

namespace App\Support;

use App\Filament\Resources\DberpCustomerReceivables\DberpCustomerReceivableResource;
use App\Filament\Resources\DberpPaymentOrders\DberpPaymentOrderResource;
use App\Filament\Resources\DberpPurchaseOrders\DberpPurchaseOrderResource;
use App\Filament\Resources\DberpReceiptOrders\DberpReceiptOrderResource;
use App\Filament\Resources\DberpSalesOrders\DberpSalesOrderResource;
use App\Filament\Resources\DberpSettlementAdjustments\DberpSettlementAdjustmentResource;
use App\Filament\Resources\DberpSettlementWriteOffs\DberpSettlementWriteOffResource;
use App\Filament\Resources\DberpSupplierPayables\DberpSupplierPayableResource;
use App\Models\DberpPayableRecord;
use App\Models\DberpReceivableRecord;
use App\Models\DberpSettlementEntry;
use Filament\Resources\Resource;

final class DberpSettlementEntrySourceUrlResolver
{
    /** @var array<string, class-string<resource>> */
    private const array RESOURCE_BY_SOURCE_TYPE = [
        'sales_order' => DberpSalesOrderResource::class,
        'purchase_order' => DberpPurchaseOrderResource::class,
        'receipt_order' => DberpReceiptOrderResource::class,
        'payment_order' => DberpPaymentOrderResource::class,
        'settlement_write_off' => DberpSettlementWriteOffResource::class,
        'settlement_adjustment' => DberpSettlementAdjustmentResource::class,
    ];

    public static function editUrlOrNull(?DberpSettlementEntry $entry): ?string
    {
        if ($entry === null) {
            return null;
        }

        return self::editUrl($entry);
    }

    public static function hasEditUrl(?DberpSettlementEntry $entry): bool
    {
        return self::editUrlOrNull($entry) !== null;
    }

    public static function editUrl(DberpSettlementEntry $entry): ?string
    {
        $sourceType = (string) $entry->source_type;
        $sourceId = (int) ($entry->source_id ?? 0);

        if ($sourceId <= 0) {
            return null;
        }

        return match ($sourceType) {
            'receivable_record' => self::receivableRecordUrl($sourceId),
            'payable_record' => self::payableRecordUrl($sourceId),
            default => self::resourceEditUrl($sourceType, $sourceId),
        };
    }

    private static function resourceEditUrl(string $sourceType, int $sourceId): ?string
    {
        $resourceClass = self::RESOURCE_BY_SOURCE_TYPE[$sourceType] ?? null;

        if ($resourceClass === null) {
            return null;
        }

        return $resourceClass::getUrl('edit', ['record' => $sourceId]);
    }

    private static function receivableRecordUrl(int $receivableRecordId): ?string
    {
        $record = DberpReceivableRecord::query()->find($receivableRecordId);

        if ($record === null) {
            return null;
        }

        if ($record->source_type === 'sales_order' && $record->source_id !== null) {
            return DberpSalesOrderResource::getUrl('edit', ['record' => (int) $record->source_id]);
        }

        return DberpFilamentListPageUrl::append(
            DberpCustomerReceivableResource::getUrl('index'),
            ['customer_id' => ['value' => (int) $record->customer_id]],
        );
    }

    private static function payableRecordUrl(int $payableRecordId): ?string
    {
        $record = DberpPayableRecord::query()->find($payableRecordId);

        if ($record === null) {
            return null;
        }

        if ($record->source_type === 'purchase_order' && $record->source_id !== null) {
            return DberpPurchaseOrderResource::getUrl('edit', ['record' => (int) $record->source_id]);
        }

        return DberpFilamentListPageUrl::append(
            DberpSupplierPayableResource::getUrl('index'),
            ['supplier_id' => ['value' => (int) $record->supplier_id]],
        );
    }
}
