<?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 Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

/**
 * 单规格模式下默认规格组合与主档摘要字段的维护。
 */
final class ProductSkuLifecycleService
{
    public function syncAfterProductSaved(DberpProduct $product): void
    {
        if ($product->spec_enabled) {
            return;
        }

        $this->enforceSingleSpecMode($product);
    }

    public function enforceSingleSpecMode(DberpProduct $product): void
    {
        DB::transaction(function () use ($product): void {
            DberpProductSku::createDefaultForProduct($product);

            $skus = DberpProductSku::query()
                ->where('product_id', $product->getKey())
                ->orderBy('sort_order')
                ->orderBy('id')
                ->get();

            if ($skus->isEmpty()) {
                return;
            }

            $default = $skus->firstWhere('is_default', true) ?? $skus->first();
            if ($default === null) {
                return;
            }

            foreach ($skus as $sku) {
                if ($sku->is($default)) {
                    $sku->forceFill([
                        'is_default' => true,
                        'is_enabled' => (bool) $product->is_enabled,
                        'spec_text' => $product->spec_model,
                    ])->save();

                    continue;
                }

                $hasStock = ProductSkuReferenceGuard::hasPositiveRealtimeStock((int) $sku->getKey());

                $sku->forceFill([
                    'is_default' => false,
                    'is_enabled' => $hasStock ? (bool) $sku->getAttribute('is_enabled') : false,
                ])->save();
            }
        });
    }

    public function canPhysicallyDeleteSpecCombo(DberpProductSku $sku): bool
    {
        if ($sku->is_enabled) {
            return false;
        }

        $product = $sku->relationLoaded('product') ? $sku->product : $sku->product()->first();
        if ($product instanceof DberpProduct && $product->spec_enabled) {
            $skuCount = DberpProductSku::query()->where('product_id', $product->getKey())->count();
            if ($skuCount <= 1) {
                return false;
            }
        }

        return ProductSkuReferenceGuard::isSafeForPhysicalDeletion((int) $sku->getKey());
    }

    /**
     * @throws ValidationException
     */
    public function physicallyDeleteSpecComboIfAllowed(DberpProductSku $sku): void
    {
        if ($sku->is_enabled) {
            throw ValidationException::withMessages([
                'is_enabled' => (string) __('dberp.validation.product_spec_combo_delete_requires_disabled'),
            ]);
        }

        $product = $sku->relationLoaded('product') ? $sku->product : $sku->product()->first();
        if ($product instanceof DberpProduct && $product->spec_enabled) {
            $skuCount = DberpProductSku::query()->where('product_id', $product->getKey())->count();
            if ($skuCount <= 1) {
                throw ValidationException::withMessages([
                    'product_sku_id' => (string) __('dberp.validation.product_spec_combo_delete_blocked_last'),
                ]);
            }
        }

        ProductSkuReferenceGuard::assertCanPhysicallyDelete($sku);

        $productId = (int) $sku->product_id;
        $wasDefault = (bool) $sku->is_default;

        DB::transaction(function () use ($sku, $productId, $wasDefault): void {
            $sku->delete();

            if ($wasDefault) {
                $this->ensureDefaultSkuForProductId($productId);
            }
        });
    }

    private function ensureDefaultSkuForProductId(int $productId): void
    {
        $hasDefault = DberpProductSku::query()
            ->where('product_id', $productId)
            ->where('is_default', true)
            ->exists();

        if ($hasDefault) {
            return;
        }

        $first = DberpProductSku::query()
            ->where('product_id', $productId)
            ->orderBy('sort_order')
            ->orderBy('id')
            ->first();

        if ($first !== null) {
            $first->forceFill(['is_default' => true])->save();
        }
    }
}
