<?php

declare(strict_types=1);

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

namespace App\Business\MasterData;

use App\Business\Purchase\Enums\PurchaseOrderReceiptStatus;
use App\Business\Purchase\Enums\PurchaseOrderStatus;
use App\Business\Report\PurchaseAnalysisReportService;
use App\Business\Settlement\PartnerSettlementSnapshotQuery;
use App\Models\DberpPurchaseOrder;
use App\Models\DberpSupplier;
use App\Support\DberpNumberFormatter;
use App\Tools\Entity\EntityType;
use App\Tools\Exceptions\ToolResourceNotFoundException;
use App\Tools\Support\ToolUniqueRecordLookup;

/**
 * 供应商只读经营快照。采购口径复用采购分析报表，未结/逾期复用应付 overdue_status，
 * 未完成订单复用 purchase.order.search 的 receipt_status=open。不走 Filament 全景服务。
 */
final class SupplierBusinessSummaryQuery
{
    public function __construct(
        private readonly PurchaseAnalysisReportService $purchaseAnalysisReportService,
        private readonly PartnerSettlementSnapshotQuery $settlementSnapshotQuery,
    ) {}

    /**
     * @param  array<string, mixed>  $input
     * @param  array{code: string, meaning: string}  $currency
     * @return array<string, mixed>
     */
    public function summarize(array $input, string $asOfDate, array $currency): array
    {
        $period = PartnerBusinessSummarySupport::resolvePeriod($input, $asOfDate);
        $supplier = ToolUniqueRecordLookup::findOne(DberpSupplier::query(), $input);

        if (! $supplier instanceof DberpSupplier) {
            throw ToolResourceNotFoundException::forLookup();
        }

        $supplierId = (int) $supplier->getKey();

        return [
            'supplier' => PartnerBusinessSummarySupport::identity(
                $supplierId,
                (string) $supplier->code,
                (string) $supplier->name,
                (bool) $supplier->is_enabled,
                EntityType::Supplier,
            ),
            'as_of_date' => $asOfDate,
            'purchases' => $this->purchaseTotals(['supplier_id' => $supplierId]),
            'recent_purchases' => [
                'period' => [
                    'from' => $period['from'],
                    'until' => $period['until'],
                ],
                ...$this->purchaseTotals([
                    'supplier_id' => $supplierId,
                    'business_time_from' => $period['from'],
                    'business_time_until' => $period['until'],
                ]),
            ],
            'open_orders' => $this->openOrders($supplierId),
            'outstanding_payables' => $this->settlementSnapshotQuery->payableOpen($supplierId),
            'overdue_payables' => $this->settlementSnapshotQuery->payableOverdue($supplierId, $asOfDate),
            'last_business_date' => $this->lastBusinessDate($supplierId),
            'currency' => $currency,
        ];
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array{
     *     order_count: int,
     *     total_amount: string,
     *     paid_amount: string,
     *     unpaid_amount: string,
     *     total_quantity: string,
     *     remaining_arrival_quantity: string
     * }
     */
    private function purchaseTotals(array $filters): array
    {
        $summary = $this->purchaseAnalysisReportService->summary(
            $this->purchaseAnalysisReportService->normalizeFilters($filters),
        );

        return [
            'order_count' => (int) $summary['order_count'],
            'total_amount' => (string) $summary['total_amount'],
            'paid_amount' => (string) $summary['paid_amount'],
            'unpaid_amount' => (string) $summary['unpaid_amount'],
            'total_quantity' => (string) $summary['total_quantity'],
            'remaining_arrival_quantity' => (string) $summary['remaining_arrival_quantity'],
        ];
    }

    /**
     * @return array{count: int, amount: string}
     */
    private function openOrders(int $supplierId): array
    {
        $query = DberpPurchaseOrder::query()
            ->where('supplier_id', $supplierId)
            ->whereIn('status', PurchaseOrderReceiptStatus::Open->statusValues());

        return [
            'count' => (int) (clone $query)->count(),
            'amount' => DberpNumberFormatter::money((clone $query)->sum('total_amount')),
        ];
    }

    private function lastBusinessDate(int $supplierId): ?string
    {
        $latest = DberpPurchaseOrder::query()
            ->where('supplier_id', $supplierId)
            ->whereIn('status', PurchaseOrderStatus::statisticsScopeValues())
            ->max('business_time');

        return PartnerBusinessSummarySupport::calendarDate($latest);
    }
}
