<?php

declare(strict_types=1);

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

namespace App\Business\Product;

use App\Models\DberpProduct;
use App\Models\DberpProductSku;
use App\Support\DberpNumberFormatter;
use App\Tools\Exceptions\ToolResourceNotFoundException;
use App\Tools\Support\ToolUniqueRecordLookup;

/**
 * 单商品只读详情。SKU 仅返回受控摘要，不带出成本、备注或任意关联。
 */
final class ProductReadQuery
{
    public function __construct(
        private readonly ProductSearchQuery $searchQuery,
    ) {}

    /**
     * @param  array<string, mixed>  $input
     * @return array<string, mixed>
     */
    public function find(array $input): array
    {
        $product = ToolUniqueRecordLookup::findOne(
            DberpProduct::query()->with(['category', 'unit', 'brand', 'skus']),
            $input,
        );

        if (! $product instanceof DberpProduct) {
            throw ToolResourceNotFoundException::forLookup();
        }

        $payload = $this->searchQuery->mapSummary($product);
        $payload['skus'] = $product->skus
            ->sortBy([
                ['sort_order', 'asc'],
                ['id', 'asc'],
            ])
            ->map(fn (DberpProductSku $sku): array => $this->mapSku($sku))
            ->values()
            ->all();

        return $payload;
    }

    /**
     * @return array<string, mixed>
     */
    private function mapSku(DberpProductSku $sku): array
    {
        return [
            'id' => (int) $sku->getKey(),
            'sku_code' => (string) $sku->sku_code,
            'barcode' => $this->nullableString($sku->barcode),
            'spec_text' => $this->nullableString($sku->spec_text),
            'is_enabled' => (bool) $sku->is_enabled,
            'is_default' => (bool) $sku->is_default,
            'sales_price' => DberpNumberFormatter::price($sku->sales_price),
        ];
    }

    private function nullableString(mixed $value): ?string
    {
        if ($value === null) {
            return null;
        }

        $normalized = trim((string) $value);

        return $normalized === '' ? null : $normalized;
    }
}
