<?php

declare(strict_types=1);

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

namespace App\Tools\Product;

use App\Business\Product\Enums\ProductSalesActivity;
use App\Business\Product\Enums\ProductSalesChange;
use App\Business\Product\ProductPerformanceSearchQuery;
use App\Tools\Entity\EntityReferenceSchema;
use App\Tools\Support\ToolDateSchema;
use App\Tools\Support\ToolListSchema;

/**
 * 商品经营多条件检索的输入/输出白名单。
 */
final class ProductPerformanceToolSchema
{
    /**
     * @return array<string, mixed>
     */
    public static function input(): array
    {
        $threshold = static fn (): array => [
            'type' => 'number',
            'minimum' => 0,
        ];

        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'q' => [
                    'type' => 'string',
                    'minLength' => 1,
                    'maxLength' => 100,
                ],
                'is_enabled' => ['type' => 'boolean'],
                'category_id' => ['type' => 'integer', 'minimum' => 1],
                'product_id' => ['type' => 'integer', 'minimum' => 1],
                'product_sku_id' => ['type' => 'integer', 'minimum' => 1],
                'warehouse_id' => ['type' => 'integer', 'minimum' => 1],
                'customer_id' => ['type' => 'integer', 'minimum' => 1],
                'supplier_id' => ['type' => 'integer', 'minimum' => 1],
                'date_from' => ToolDateSchema::dateProperty('Inclusive sales/purchase business calendar date Y-m-d.'),
                'date_until' => ToolDateSchema::dateProperty('Inclusive sales/purchase business calendar date Y-m-d.'),
                'period_preset' => ToolDateSchema::periodPresetProperty(),
                'sales_quantity_min' => $threshold(),
                'sales_quantity_max' => $threshold(),
                'sales_amount_min' => $threshold(),
                'sales_amount_max' => $threshold(),
                'purchase_quantity_min' => $threshold(),
                'purchase_quantity_max' => $threshold(),
                'purchase_amount_min' => $threshold(),
                'purchase_amount_max' => $threshold(),
                'stock_quantity_min' => $threshold(),
                'stock_quantity_max' => $threshold(),
                'available_quantity_min' => $threshold(),
                'available_quantity_max' => $threshold(),
                'sales_activity' => [
                    'type' => 'string',
                    'enum' => ProductSalesActivity::values(),
                ],
                'sales_change' => [
                    'type' => 'string',
                    'enum' => ProductSalesChange::values(),
                    'description' => 'Requires date_from and date_until. Compares the equal-length preceding window.',
                ],
                ...ToolListSchema::paginationInputProperties(
                    ProductPerformanceSearchQuery::SORTABLE,
                    ProductPerformanceSearchQuery::DEFAULT_SORT,
                ),
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function output(): array
    {
        $schema = ToolListSchema::paginatedOutputSchemaWithCurrency(self::item());
        $schema['required'][] = 'period';
        $schema['required'][] = 'comparison_period';
        $schema['properties']['period'] = self::periodSchema();
        $schema['properties']['comparison_period'] = [
            'type' => ['object', 'null'],
            'required' => ['from', 'until'],
            'additionalProperties' => false,
            'properties' => [
                'from' => ['type' => 'string'],
                'until' => ['type' => 'string'],
            ],
        ];

        return $schema;
    }

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

    /**
     * @return array<string, mixed>
     */
    private static function item(): array
    {
        return [
            'type' => 'object',
            'required' => [
                'id',
                'code',
                'name',
                'is_enabled',
                'sales_quantity',
                'sales_amount',
                'purchase_quantity',
                'purchase_amount',
                'current_stock_quantity',
                'available_stock_quantity',
                'sales_activity',
            ],
            'additionalProperties' => false,
            'properties' => [
                'id' => ['type' => 'integer'],
                'code' => ['type' => 'string'],
                'name' => ['type' => 'string'],
                'is_enabled' => ['type' => 'boolean'],
                'category_id' => ['type' => 'integer'],
                'category_name' => ['type' => 'string'],
                'sales_quantity' => ['type' => 'string'],
                'sales_amount' => ['type' => 'string'],
                'purchase_quantity' => ['type' => 'string'],
                'purchase_amount' => ['type' => 'string'],
                'current_stock_quantity' => ['type' => 'string'],
                'available_stock_quantity' => ['type' => 'string'],
                'sales_activity' => [
                    'type' => 'string',
                    'enum' => ProductSalesActivity::values(),
                ],
                'previous_sales_quantity' => ['type' => ['string', 'null']],
                'previous_sales_amount' => ['type' => ['string', 'null']],
                'sales_change' => [
                    'type' => ['string', 'null'],
                    'enum' => array_merge(ProductSalesChange::values(), [null]),
                ],
                'entity_ref' => EntityReferenceSchema::object(),
            ],
        ];
    }
}
