<?php

declare(strict_types=1);

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

namespace App\Tools\MasterData;

use App\Tools\Entity\EntityReferenceSchema;
use App\Tools\Support\ToolCurrency;
use App\Tools\Support\ToolDateSchema;

/**
 * 客户/供应商详情与经营快照共用 JSON Schema。仅描述已批准业务字段。
 */
final class PartnerToolSchema
{
    /**
     * @return array<string, mixed>
     */
    public static function lookupInput(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'id' => ['type' => 'integer', 'minimum' => 1],
                'code' => [
                    'type' => 'string',
                    'minLength' => 1,
                    'maxLength' => 64,
                ],
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function summaryInput(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'id' => ['type' => 'integer', 'minimum' => 1],
                'code' => [
                    'type' => 'string',
                    'minLength' => 1,
                    'maxLength' => 64,
                ],
                'date_from' => ToolDateSchema::dateProperty('Inclusive business calendar date Y-m-d for the recent window.'),
                'date_until' => ToolDateSchema::dateProperty('Inclusive business calendar date Y-m-d for the recent window.'),
                'period_preset' => ToolDateSchema::periodPresetProperty(),
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function identity(): array
    {
        return EntityReferenceSchema::withRef([
            'type' => 'object',
            'required' => ['id', 'code', 'name', 'is_enabled'],
            'additionalProperties' => false,
            'properties' => [
                'id' => ['type' => 'integer'],
                'code' => ['type' => 'string'],
                'name' => ['type' => 'string'],
                'is_enabled' => ['type' => 'boolean'],
            ],
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public static function countAmount(): array
    {
        return [
            'type' => 'object',
            'required' => ['count', 'amount'],
            'additionalProperties' => false,
            'properties' => [
                'count' => ['type' => 'integer'],
                'amount' => ['type' => 'string'],
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function period(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'from' => ['type' => 'string'],
                'until' => ['type' => 'string'],
            ],
        ];
    }

    /**
     * @param  array<string, mixed>  $amountProperties
     * @param  list<string>  $required
     * @return array<string, mixed>
     */
    public static function totals(array $amountProperties, array $required): array
    {
        return [
            'type' => 'object',
            'required' => $required,
            'additionalProperties' => false,
            'properties' => $amountProperties,
        ];
    }

    /**
     * @param  array<string, mixed>  $amountProperties
     * @param  list<string>  $required
     * @return array<string, mixed>
     */
    public static function recentTotals(array $amountProperties, array $required): array
    {
        return [
            'type' => 'object',
            'required' => ['period', ...$required],
            'additionalProperties' => false,
            'properties' => [
                'period' => self::period(),
                ...$amountProperties,
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function salesAmountProperties(): array
    {
        return [
            'order_count' => ['type' => 'integer'],
            'final_amount' => ['type' => 'string'],
            'receivable_amount' => ['type' => 'string'],
            'received_amount' => ['type' => 'string'],
            'unreceived_amount' => ['type' => 'string'],
            'total_quantity' => ['type' => 'string'],
        ];
    }

    /**
     * @return list<string>
     */
    public static function salesAmountRequired(): array
    {
        return [
            'order_count',
            'final_amount',
            'receivable_amount',
            'received_amount',
            'unreceived_amount',
            'total_quantity',
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function purchaseAmountProperties(): array
    {
        return [
            'order_count' => ['type' => 'integer'],
            'total_amount' => ['type' => 'string'],
            'paid_amount' => ['type' => 'string'],
            'unpaid_amount' => ['type' => 'string'],
            'total_quantity' => ['type' => 'string'],
            'remaining_arrival_quantity' => ['type' => 'string'],
        ];
    }

    /**
     * @return list<string>
     */
    public static function purchaseAmountRequired(): array
    {
        return [
            'order_count',
            'total_amount',
            'paid_amount',
            'unpaid_amount',
            'total_quantity',
            'remaining_arrival_quantity',
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function customerGetOutput(): array
    {
        return EntityReferenceSchema::withRef([
            'type' => 'object',
            'required' => [
                'id',
                'code',
                'name',
                'is_enabled',
                'sort_order',
            ],
            'additionalProperties' => false,
            'properties' => [
                'id' => ['type' => 'integer'],
                'code' => ['type' => 'string'],
                'name' => ['type' => 'string'],
                'is_enabled' => ['type' => 'boolean'],
                'customer_category_id' => ['type' => 'integer'],
                'customer_category_name' => ['type' => 'string'],
                'settlement_method' => ['type' => 'string'],
                'salesperson_employee_id' => ['type' => 'integer'],
                'salesperson_name' => ['type' => 'string'],
                'contact_person' => ['type' => 'string'],
                'sort_order' => ['type' => 'integer'],
            ],
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public static function supplierGetOutput(): array
    {
        return EntityReferenceSchema::withRef([
            'type' => 'object',
            'required' => [
                'id',
                'code',
                'name',
                'is_enabled',
                'sort_order',
            ],
            'additionalProperties' => false,
            'properties' => [
                'id' => ['type' => 'integer'],
                'code' => ['type' => 'string'],
                'name' => ['type' => 'string'],
                'is_enabled' => ['type' => 'boolean'],
                'supplier_category_id' => ['type' => 'integer'],
                'supplier_category_name' => ['type' => 'string'],
                'settlement_method' => ['type' => 'string'],
                'contact_person' => ['type' => 'string'],
                'sort_order' => ['type' => 'integer'],
            ],
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    public static function customerSummaryOutput(): array
    {
        return [
            'type' => 'object',
            'required' => [
                'customer',
                'as_of_date',
                'sales',
                'recent_sales',
                'open_orders',
                'outstanding_receivables',
                'overdue_receivables',
                'currency',
            ],
            'additionalProperties' => false,
            'properties' => [
                'customer' => self::identity(),
                'as_of_date' => ['type' => 'string'],
                'sales' => self::totals(self::salesAmountProperties(), self::salesAmountRequired()),
                'recent_sales' => self::recentTotals(self::salesAmountProperties(), self::salesAmountRequired()),
                'open_orders' => self::countAmount(),
                'outstanding_receivables' => self::countAmount(),
                'overdue_receivables' => self::countAmount(),
                'last_business_date' => ['type' => 'string'],
                'currency' => ToolCurrency::outputSchema(),
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function supplierSummaryOutput(): array
    {
        return [
            'type' => 'object',
            'required' => [
                'supplier',
                'as_of_date',
                'purchases',
                'recent_purchases',
                'open_orders',
                'outstanding_payables',
                'overdue_payables',
                'currency',
            ],
            'additionalProperties' => false,
            'properties' => [
                'supplier' => self::identity(),
                'as_of_date' => ['type' => 'string'],
                'purchases' => self::totals(self::purchaseAmountProperties(), self::purchaseAmountRequired()),
                'recent_purchases' => self::recentTotals(self::purchaseAmountProperties(), self::purchaseAmountRequired()),
                'open_orders' => self::countAmount(),
                'outstanding_payables' => self::countAmount(),
                'overdue_payables' => self::countAmount(),
                'last_business_date' => ['type' => 'string'],
                'currency' => ToolCurrency::outputSchema(),
            ],
        ];
    }
}
