<?php

declare(strict_types=1);

namespace App\Models;

use App\Business\Product\DberpDocumentLineUnitService;
use App\Models\Concerns\HasDberpDocumentLineUnitRelations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class DberpPurchaseRequestItem extends Model
{
    use HasDberpDocumentLineUnitRelations;

    protected $table = 'dberp_purchase_request_items';

    /**
     * @var list<string>
     */
    protected $fillable = [
        'request_id',
        'product_id',
        'product_sku_id',
        'product_sku_code',
        'product_sku_name',
        'product_sku_spec',
        'unit_id',
        'unit_name',
        'base_unit_id',
        'auxiliary_unit_id',
        'is_auxiliary_unit',
        'auxiliary_unit_quantity',
        'base_unit_quantity',
        'external_product_id',
        'external_sku',
        'warehouse_id',
        'source_type',
        'source_id',
        'source_reference_no',
        'source_snapshot',
        'request_quantity',
        'converted_quantity',
        'remaining_quantity',
        'sort_order',
        'remark',
    ];

    protected static function booted(): void
    {
        static::saving(function (self $item): void {
            DberpDocumentLineUnitService::applySnapshotsToLine($item);

            $requestQuantity = (float) ($item->request_quantity ?? 0);
            $convertedQuantity = (float) ($item->converted_quantity ?? 0);
            $remainingQuantity = max($requestQuantity - $convertedQuantity, 0);

            $item->setAttribute('remaining_quantity', number_format($remainingQuantity, 4, '.', ''));
        });

        static::saved(function (self $item): void {
            $item->request?->forceFill([
                'total_quantity' => (string) $item->request->items()->sum('request_quantity'),
                'converted_quantity' => (string) $item->request->items()->sum('converted_quantity'),
                'remaining_quantity' => (string) $item->request->items()->sum('remaining_quantity'),
            ])->save();
        });

        static::deleted(function (self $item): void {
            $item->request?->forceFill([
                'total_quantity' => (string) $item->request->items()->sum('request_quantity'),
                'converted_quantity' => (string) $item->request->items()->sum('converted_quantity'),
                'remaining_quantity' => (string) $item->request->items()->sum('remaining_quantity'),
            ])->save();
        });
    }

    protected function casts(): array
    {
        return [
            'request_id' => 'integer',
            'product_id' => 'integer',
            'product_sku_id' => 'integer',
            'unit_id' => 'integer',
            'base_unit_id' => 'integer',
            'auxiliary_unit_id' => 'integer',
            'is_auxiliary_unit' => 'boolean',
            'auxiliary_unit_quantity' => 'decimal:6',
            'base_unit_quantity' => 'decimal:6',
            'warehouse_id' => 'integer',
            'source_id' => 'integer',
            'source_snapshot' => 'array',
            'request_quantity' => 'decimal:4',
            'converted_quantity' => 'decimal:4',
            'remaining_quantity' => 'decimal:4',
            'sort_order' => 'integer',
        ];
    }

    public function request(): BelongsTo
    {
        return $this->belongsTo(DberpPurchaseRequest::class, 'request_id');
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(DberpProduct::class, 'product_id');
    }

    public function productSku(): BelongsTo
    {
        return $this->belongsTo(DberpProductSku::class, 'product_sku_id');
    }

    public function warehouse(): BelongsTo
    {
        return $this->belongsTo(DberpWarehouse::class, 'warehouse_id');
    }

    public function purchaseOrderItems(): HasMany
    {
        return $this->hasMany(DberpPurchaseOrderItem::class, 'purchase_request_item_id');
    }

    public function inquiryItems(): HasMany
    {
        return $this->hasMany(DberpPurchaseInquiryItem::class, 'purchase_request_item_id');
    }

    public function inquiryQuotes(): HasMany
    {
        return $this->hasMany(DberpPurchaseInquiryQuote::class, 'purchase_request_item_id');
    }
}
