<?php

declare(strict_types=1);

namespace App\Business\Report;

use App\Support\DberpNumberFormatter;

final class ComprehensiveSummaryAnalysisService
{
    public function __construct(
        private readonly SalesAnalysisReportService $salesAnalysisReportService,
        private readonly PurchaseAnalysisReportService $purchaseAnalysisReportService,
        private readonly InventoryAnalysisReportService $inventoryAnalysisReportService,
        private readonly SettlementAnalysisReportService $settlementAnalysisReportService,
    ) {}

    /**
     * @param  array<string, mixed>  $formState
     * @return array<string, mixed>
     */
    public function normalizeFilters(array $formState): array
    {
        $filters = [
            'business_time_from' => $formState['business_time_from'] ?? null,
            'business_time_until' => $formState['business_time_until'] ?? null,
            'as_of_date' => $formState['as_of_date'] ?? null,
            'customer_id' => (int) ($formState['customer_id'] ?? 0),
            'supplier_id' => (int) ($formState['supplier_id'] ?? 0),
            'warehouse_id' => (int) ($formState['warehouse_id'] ?? 0),
            'category_id' => (int) ($formState['category_id'] ?? 0),
            'product_id' => (int) ($formState['product_id'] ?? 0),
        ];

        foreach (['customer_id', 'supplier_id', 'warehouse_id', 'category_id', 'product_id'] as $key) {
            if ($filters[$key] <= 0) {
                unset($filters[$key]);
            }
        }

        if (empty($filters['business_time_from'])) {
            unset($filters['business_time_from']);
        }
        if (empty($filters['business_time_until'])) {
            unset($filters['business_time_until']);
        }
        if (empty($filters['as_of_date'])) {
            unset($filters['as_of_date']);
        }

        return $filters;
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, int|string|float>
     */
    public function salesSummary(array $filters): array
    {
        return $this->salesAnalysisReportService->summary($this->salesFilters($filters));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, int|string|float>
     */
    public function purchaseSummary(array $filters): array
    {
        return $this->purchaseAnalysisReportService->summary($this->purchaseFilters($filters));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, int|string|float>
     */
    public function inventorySummary(array $filters): array
    {
        return $this->inventoryAnalysisReportService->summary($this->inventoryFilters($filters));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, int|string|float>
     */
    public function settlementSummary(array $filters): array
    {
        return $this->settlementAnalysisReportService->summary($this->settlementFilters($filters));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return list<array{date: string, sales_amount: string, purchase_amount: string, inbound_quantity: string, outbound_quantity: string, receipt_amount: string, payment_amount: string}>
     */
    public function trendOverview(array $filters): array
    {
        $rows = [];

        foreach ($this->salesAnalysisReportService->dailyTrend($this->salesFilters($filters)) as $row) {
            $this->seedTrendRow($rows, $row['date']);
            $rows[$row['date']]['sales_amount'] = $row['amount'];
        }

        foreach ($this->purchaseAnalysisReportService->dailyTrend($this->purchaseFilters($filters)) as $row) {
            $this->seedTrendRow($rows, $row['date']);
            $rows[$row['date']]['purchase_amount'] = $row['amount'];
        }

        foreach ($this->inventoryAnalysisReportService->dailyFlowTrend($this->inventoryFilters($filters)) as $row) {
            $this->seedTrendRow($rows, $row['date']);
            $rows[$row['date']]['inbound_quantity'] = $row['inbound'];
            $rows[$row['date']]['outbound_quantity'] = $row['outbound'];
        }

        foreach ($this->settlementAnalysisReportService->dailyReceiptTrend($this->settlementFilters($filters)) as $row) {
            $this->seedTrendRow($rows, $row['date']);
            $rows[$row['date']]['receipt_amount'] = $row['amount'];
        }

        foreach ($this->settlementAnalysisReportService->dailyPaymentTrend($this->settlementFilters($filters)) as $row) {
            $this->seedTrendRow($rows, $row['date']);
            $rows[$row['date']]['payment_amount'] = $row['amount'];
        }

        ksort($rows);

        return array_values($rows);
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, mixed>
     */
    private function salesFilters(array $filters): array
    {
        return array_intersect_key($filters, array_flip([
            'business_time_from',
            'business_time_until',
            'customer_id',
            'category_id',
            'product_id',
        ]));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, mixed>
     */
    private function purchaseFilters(array $filters): array
    {
        return array_intersect_key($filters, array_flip([
            'business_time_from',
            'business_time_until',
            'supplier_id',
            'category_id',
            'product_id',
        ]));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, mixed>
     */
    private function inventoryFilters(array $filters): array
    {
        return array_intersect_key($filters, array_flip([
            'business_time_from',
            'business_time_until',
            'warehouse_id',
            'category_id',
            'product_id',
        ]));
    }

    /**
     * @param  array<string, mixed>  $filters
     * @return array<string, mixed>
     */
    private function settlementFilters(array $filters): array
    {
        return array_intersect_key($filters, array_flip([
            'business_time_from',
            'business_time_until',
            'as_of_date',
            'customer_id',
            'supplier_id',
        ]));
    }

    /**
     * @param  array<string, array{date: string, sales_amount: string, purchase_amount: string, inbound_quantity: string, outbound_quantity: string, receipt_amount: string, payment_amount: string}>  $rows
     */
    private function seedTrendRow(array &$rows, string $date): void
    {
        if (isset($rows[$date])) {
            return;
        }

        $rows[$date] = [
            'date' => $date,
            'sales_amount' => DberpNumberFormatter::money(0),
            'purchase_amount' => DberpNumberFormatter::money(0),
            'inbound_quantity' => DberpNumberFormatter::quantity(0),
            'outbound_quantity' => DberpNumberFormatter::quantity(0),
            'receipt_amount' => DberpNumberFormatter::money(0),
            'payment_amount' => DberpNumberFormatter::money(0),
        ];
    }
}
