<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Business\Settlement;

use App\Models\DberpPurchaseOrder;
use App\Models\DberpSalesOrder;
use App\Support\DberpDocumentRemarkPropagation;
use App\Support\DberpNumberFormatter;

final class SettlementReceiptPaymentReferenceDefaultsResolver
{
    public function __construct(
        private readonly PayableService $payableService,
        private readonly ReceivableService $receivableService,
    ) {}

    /**
     * @return array<string, int|null>
     */
    public function resolveFromPurchaseOrder(DberpPurchaseOrder $order): array
    {
        return [
            'supplier_id' => (int) $order->supplier_id,
            'handler_employee_id' => $order->handler_employee_id !== null ? (int) $order->handler_employee_id : null,
            'remark' => DberpDocumentRemarkPropagation::trimmedOrNull($order->remark),
        ];
    }

    /**
     * @return array<string, int|null>
     */
    public function resolveFromSalesOrder(DberpSalesOrder $order): array
    {
        return [
            'customer_id' => (int) $order->customer_id,
            'handler_employee_id' => $order->handler_employee_id !== null ? (int) $order->handler_employee_id : null,
            'remark' => DberpDocumentRemarkPropagation::trimmedOrNull($order->remark),
        ];
    }

    /**
     * @return array{payable_amount: string, paid_amount: string, unpaid_amount: string}|null
     */
    public function purchaseOrderSettlementAmounts(?int $purchaseOrderId): ?array
    {
        if ($purchaseOrderId === null || $purchaseOrderId <= 0) {
            return null;
        }

        $order = DberpPurchaseOrder::query()->find($purchaseOrderId);

        if (! $order instanceof DberpPurchaseOrder) {
            return null;
        }

        return [
            'payable_amount' => $this->formatAmount((string) $order->payable_amount),
            'paid_amount' => $this->formatAmount((string) $order->paid_amount),
            'unpaid_amount' => $this->payableService->remainingAmount($order),
        ];
    }

    /**
     * @return array{receivable_amount: string, received_amount: string, unreceived_amount: string}|null
     */
    public function salesOrderSettlementAmounts(?int $salesOrderId): ?array
    {
        if ($salesOrderId === null || $salesOrderId <= 0) {
            return null;
        }

        $order = DberpSalesOrder::query()->find($salesOrderId);

        if (! $order instanceof DberpSalesOrder) {
            return null;
        }

        return [
            'receivable_amount' => $this->formatAmount((string) $order->receivable_amount),
            'received_amount' => $this->formatAmount((string) $order->received_amount),
            'unreceived_amount' => $this->receivableService->remainingAmount($order),
        ];
    }

    public function formatPurchaseOrderSettlementSummary(?int $purchaseOrderId): string
    {
        $amounts = $this->purchaseOrderSettlementAmounts($purchaseOrderId);

        if ($amounts === null) {
            return '';
        }

        return implode('　', [
            __('dberp.fields.payable_amount').'：'.DberpNumberFormatter::money($amounts['payable_amount']),
            __('dberp.fields.paid_amount').'：'.DberpNumberFormatter::money($amounts['paid_amount']),
            __('dberp.fields.unpaid_amount').'：'.DberpNumberFormatter::money($amounts['unpaid_amount']),
        ]);
    }

    public function formatSalesOrderSettlementSummary(?int $salesOrderId): string
    {
        $amounts = $this->salesOrderSettlementAmounts($salesOrderId);

        if ($amounts === null) {
            return '';
        }

        return implode('　', [
            __('dberp.fields.receivable_amount').'：'.DberpNumberFormatter::money($amounts['receivable_amount']),
            __('dberp.fields.received_amount').'：'.DberpNumberFormatter::money($amounts['received_amount']),
            __('dberp.fields.unreceived_amount').'：'.DberpNumberFormatter::money($amounts['unreceived_amount']),
        ]);
    }

    public function suggestPaymentAmountFromPurchaseOrder(?int $purchaseOrderId): ?string
    {
        $amounts = $this->purchaseOrderSettlementAmounts($purchaseOrderId);

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

        return $this->suggestAmountFromOutstanding($amounts['unpaid_amount']);
    }

    public function suggestReceiptAmountFromSalesOrder(?int $salesOrderId): ?string
    {
        $amounts = $this->salesOrderSettlementAmounts($salesOrderId);

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

        return $this->suggestAmountFromOutstanding($amounts['unreceived_amount']);
    }

    private function suggestAmountFromOutstanding(string $outstandingAmount): ?string
    {
        if ((float) $outstandingAmount <= 0.00005) {
            return null;
        }

        return $this->formatAmount($outstandingAmount);
    }

    private function formatAmount(string $amount): string
    {
        return number_format((float) $amount, 4, '.', '');
    }
}
