<?php

declare(strict_types=1);

namespace App\Business\Inventory;

use App\Models\DberpInventoryBalance;
use App\Models\DberpInventoryRule;
use App\Models\DberpSystemProfile;

final class InventoryRuleService
{
    public function profile(): DberpSystemProfile
    {
        return DberpSystemProfile::query()->firstOrCreate(
            ['id' => 1],
            DberpSystemProfile::defaultAttributes(),
        );
    }

    public function allowNegativeStock(): bool
    {
        return (bool) $this->profile()->allow_negative_stock;
    }

    public function defaultWarehouseId(): ?int
    {
        $warehouseId = $this->profile()->default_warehouse_id;

        return $warehouseId === null ? null : (int) $warehouseId;
    }

    public function documentVoidPolicy(): string
    {
        return (string) $this->profile()->document_void_policy;
    }

    public function allowsEffectiveInventoryVoid(): bool
    {
        return $this->documentVoidPolicy() !== 'forbid_if_posted';
    }

    public function allowsVoidMarkOnly(): bool
    {
        return $this->documentVoidPolicy() === 'mark_only';
    }

    public function allowVoidRollback(): bool
    {
        return $this->documentVoidPolicy() === 'restore_stock_and_finance';
    }

    public function safetyStockAlertEnabled(): bool
    {
        return (bool) $this->profile()->safety_stock_alert_enabled;
    }

    /**
     * 将规则上的安全库存同步到该商品在该仓下所有库存余额行，供「库存预警」按余额表字段判断。
     * 启用预警且规则启用时写入规则值；否则将该仓该商品下各余额行的安全库存清零。
     */
    public function syncSafetyStockToBalances(DberpInventoryRule $rule): int
    {
        $query = DberpInventoryBalance::query()
            ->where('product_id', $rule->product_id)
            ->where('warehouse_id', $rule->warehouse_id);

        if ($rule->is_enabled && $rule->warning_enabled) {
            $value = number_format((float) (string) $rule->safety_stock, 4, '.', '');

            return $query->update(['safety_stock' => $value]);
        }

        return $query->update(['safety_stock' => '0.0000']);
    }

    /**
     * 在商品或仓库维度变更后，清除原维度下余额行的安全库存（避免遗留旧预警阈值）。
     */
    public function clearSafetyStockOnBalances(int $productId, int $warehouseId): int
    {
        return DberpInventoryBalance::query()
            ->where('product_id', $productId)
            ->where('warehouse_id', $warehouseId)
            ->update(['safety_stock' => '0.0000']);
    }
}
