<?php

declare(strict_types=1);

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

namespace App\Tools\Support;

use App\Business\Purchase\Enums\PurchaseOrderStatus;
use App\Business\Sales\Enums\SalesOrderStatus;

/**
 * 销售/采购等长前后窗对比 Tool 的 JSON Schema。
 */
final class ToolTrendCompareSchema
{
    /**
     * @return array<string, mixed>
     */
    public static function salesInput(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'customer_id' => ['type' => 'integer', 'minimum' => 1],
                'handler_employee_id' => ['type' => 'integer', 'minimum' => 1],
                'category_id' => ['type' => 'integer', 'minimum' => 1],
                'product_id' => ['type' => 'integer', 'minimum' => 1],
                'product_sku_id' => ['type' => 'integer', 'minimum' => 1],
                'status' => [
                    'type' => 'string',
                    'enum' => SalesOrderStatus::statisticsScopeValues(),
                ],
                'date_from' => ToolDateSchema::dateProperty('Inclusive current-period business calendar date Y-m-d. Required unless period_preset is set.'),
                'date_until' => ToolDateSchema::dateProperty('Inclusive current-period business calendar date Y-m-d. Required unless period_preset is set.'),
                'period_preset' => ToolDateSchema::periodPresetProperty(),
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function purchaseInput(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'supplier_id' => ['type' => 'integer', 'minimum' => 1],
                'handler_employee_id' => ['type' => 'integer', 'minimum' => 1],
                'category_id' => ['type' => 'integer', 'minimum' => 1],
                'product_id' => ['type' => 'integer', 'minimum' => 1],
                'status' => [
                    'type' => 'string',
                    'enum' => PurchaseOrderStatus::statisticsScopeValues(),
                ],
                'date_from' => ToolDateSchema::dateProperty('Inclusive current-period business calendar date Y-m-d. Required unless period_preset is set.'),
                'date_until' => ToolDateSchema::dateProperty('Inclusive current-period business calendar date Y-m-d. Required unless period_preset is set.'),
                'period_preset' => ToolDateSchema::periodPresetProperty(),
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function salesOutput(): array
    {
        $snapshot = [
            'order_count' => ['type' => 'integer'],
            'final_amount' => ['type' => 'string'],
            'receivable_amount' => ['type' => 'string'],
            'received_amount' => ['type' => 'string'],
            'unreceived_amount' => ['type' => 'string'],
            'total_quantity' => ['type' => 'string'],
            'confirmed_order_count' => ['type' => 'integer'],
            'partial_shipped_order_count' => ['type' => 'integer'],
            'fully_shipped_order_count' => ['type' => 'integer'],
        ];

        return self::compareOutput($snapshot, [
            'order_count',
            'final_amount',
            'receivable_amount',
            'received_amount',
            'unreceived_amount',
            'total_quantity',
            'confirmed_order_count',
            'partial_shipped_order_count',
            'fully_shipped_order_count',
            'order_count_ratio',
            'final_amount_ratio',
        ], [
            'order_count' => ['type' => 'integer'],
            'final_amount' => ['type' => 'string'],
            'receivable_amount' => ['type' => 'string'],
            'received_amount' => ['type' => 'string'],
            'unreceived_amount' => ['type' => 'string'],
            'total_quantity' => ['type' => 'string'],
            'confirmed_order_count' => ['type' => 'integer'],
            'partial_shipped_order_count' => ['type' => 'integer'],
            'fully_shipped_order_count' => ['type' => 'integer'],
            'order_count_ratio' => ['type' => ['string', 'null']],
            'final_amount_ratio' => ['type' => ['string', 'null']],
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public static function purchaseOutput(): array
    {
        $snapshot = [
            'order_count' => ['type' => 'integer'],
            'total_amount' => ['type' => 'string'],
            'paid_amount' => ['type' => 'string'],
            'unpaid_amount' => ['type' => 'string'],
            'total_quantity' => ['type' => 'string'],
            'arrived_quantity' => ['type' => 'string'],
            'remaining_arrival_quantity' => ['type' => 'string'],
            'overdue_arrival_order_count' => ['type' => 'integer'],
            'partial_received_order_count' => ['type' => 'integer'],
            'fully_received_order_count' => ['type' => 'integer'],
            'exception_count' => ['type' => 'integer'],
            'return_order_count' => ['type' => 'integer'],
        ];

        return self::compareOutput($snapshot, [
            'order_count',
            'total_amount',
            'paid_amount',
            'unpaid_amount',
            'total_quantity',
            'arrived_quantity',
            'remaining_arrival_quantity',
            'overdue_arrival_order_count',
            'partial_received_order_count',
            'fully_received_order_count',
            'exception_count',
            'return_order_count',
            'order_count_ratio',
            'total_amount_ratio',
        ], [
            'order_count' => ['type' => 'integer'],
            'total_amount' => ['type' => 'string'],
            'paid_amount' => ['type' => 'string'],
            'unpaid_amount' => ['type' => 'string'],
            'total_quantity' => ['type' => 'string'],
            'arrived_quantity' => ['type' => 'string'],
            'remaining_arrival_quantity' => ['type' => 'string'],
            'overdue_arrival_order_count' => ['type' => 'integer'],
            'partial_received_order_count' => ['type' => 'integer'],
            'fully_received_order_count' => ['type' => 'integer'],
            'exception_count' => ['type' => 'integer'],
            'return_order_count' => ['type' => 'integer'],
            'order_count_ratio' => ['type' => ['string', 'null']],
            'total_amount_ratio' => ['type' => ['string', 'null']],
        ]);
    }

    /**
     * @param  array<string, mixed>  $snapshotProperties
     * @param  list<string>  $changeRequired
     * @param  array<string, mixed>  $changeProperties
     * @return array<string, mixed>
     */
    private static function compareOutput(array $snapshotProperties, array $changeRequired, array $changeProperties): array
    {
        $period = [
            'type' => 'object',
            'required' => ['from', 'until'],
            'additionalProperties' => false,
            'properties' => [
                'from' => ['type' => 'string'],
                'until' => ['type' => 'string'],
            ],
        ];

        $snapshot = [
            'type' => 'object',
            'required' => ['period', ...array_keys($snapshotProperties)],
            'additionalProperties' => false,
            'properties' => [
                'period' => $period,
                ...$snapshotProperties,
            ],
        ];

        return [
            'type' => 'object',
            'required' => ['current', 'previous', 'change', 'currency'],
            'additionalProperties' => false,
            'properties' => [
                'current' => $snapshot,
                'previous' => $snapshot,
                'change' => [
                    'type' => 'object',
                    'required' => $changeRequired,
                    'additionalProperties' => false,
                    'properties' => $changeProperties,
                ],
                'currency' => ToolCurrency::outputSchema(),
            ],
        ];
    }
}
