<?php

declare(strict_types=1);

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

namespace App\Support;

use App\Models\DberpProduct;
use App\Models\DberpProductSku;
use Illuminate\Database\Eloquent\Model;

/**
 * 业务单据明细行：商品规格展示（优先行上快照，其次关联规格组合；不向用户暴露技术字段名）。
 */
final class DberpDocumentLineSpecPresentation
{
    public static function lineSpecAbstract(Model $line): string
    {
        $fromNew = self::trimmedStringAttr($line, 'product_sku_spec');
        if ($fromNew !== '') {
            return $fromNew;
        }

        $legacy = self::trimmedStringAttr($line, 'spec_text');
        if ($legacy !== '') {
            return $legacy;
        }

        $sku = self::productSkuIfLoaded($line);
        if ($sku instanceof DberpProductSku) {
            $t = trim((string) ($sku->spec_text ?? ''));

            return $t !== '' ? $t : '';
        }

        return '';
    }

    public static function lineSpecCode(Model $line): string
    {
        foreach (['product_sku_code', 'sku_code'] as $key) {
            $t = self::trimmedStringAttr($line, $key);
            if ($t !== '') {
                return $t;
            }
        }

        $sku = self::productSkuIfLoaded($line);
        if ($sku instanceof DberpProductSku) {
            $t = trim((string) ($sku->sku_code ?? ''));

            return $t !== '' ? $t : '';
        }

        return '';
    }

    /**
     * 列表主列「商品规格」：优先展示名称快照，其次摘要+编码组合，再次关联规格组合，最后按物料是否启用规格给出业务提示。
     */
    public static function lineSpecSummary(Model $line): string
    {
        $displayName = self::trimmedStringAttr($line, 'product_sku_name');
        if ($displayName !== '') {
            return $displayName;
        }

        $abstract = self::lineSpecAbstract($line);
        $code = self::lineSpecCode($line);
        $parts = array_values(array_filter([$abstract, $code], static fn (string $s): bool => $s !== ''));
        if ($parts !== []) {
            return implode(' · ', $parts);
        }

        $sku = self::productSkuIfLoaded($line);
        if ($sku instanceof DberpProductSku) {
            return DberpReportSkuPresentation::skuRecordSpecSummary($sku);
        }

        $product = self::productIfLoaded($line);
        if ($product instanceof DberpProduct && (bool) $product->spec_enabled) {
            return (string) __('dberp.labels.document_line_spec_not_recorded');
        }

        return '';
    }

    /**
     * @param  list<string>  $extra
     * @return list<string>
     */
    public static function eagerLoadsForDocumentLines(array $extra = []): array
    {
        return array_values(array_unique(array_merge(['product', 'productSku'], $extra)));
    }

    private static function productSkuIfLoaded(Model $line): ?DberpProductSku
    {
        if (! self::hasAttributeKey($line, 'product_sku_id')) {
            return null;
        }

        $id = (int) ($line->getAttribute('product_sku_id') ?? 0);
        if ($id <= 0) {
            return null;
        }

        if (! $line->relationLoaded('productSku')) {
            return null;
        }

        $sku = $line->getRelation('productSku');

        return $sku instanceof DberpProductSku ? $sku : null;
    }

    private static function productIfLoaded(Model $line): ?DberpProduct
    {
        if (! $line->relationLoaded('product')) {
            return null;
        }

        $p = $line->getRelation('product');

        return $p instanceof DberpProduct ? $p : null;
    }

    private static function hasAttributeKey(Model $line, string $key): bool
    {
        return array_key_exists($key, $line->getAttributes());
    }

    private static function trimmedStringAttr(Model $line, string $key): string
    {
        if (! self::hasAttributeKey($line, $key)) {
            return '';
        }

        $raw = $line->getAttribute($key);
        if ($raw === null) {
            return '';
        }

        return trim((string) $raw);
    }
}
