<?php

namespace App\Models\Inventory;

use App\Models\Catalog\Product;
use App\Models\Concerns\Auditable;
use App\Models\Concerns\BelongsToTenant;
use App\Models\Concerns\BranchScoped;
use App\Models\Customers\Customer;
use App\Models\Lookups\Status;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

class ProductSerial extends Model
{
    use Auditable, BelongsToTenant, BranchScoped, SoftDeletes;

    protected $fillable = [
        'uuid', 'product_id', 'stock_batch_id',
        'branch_id', 'current_customer_id',
        'serial_number', 'status_id',
        'purchase_price', 'warranty_expires_at', 'notes',
        'created_by', 'updated_by', 'deleted_by',
    ];

    protected function casts(): array
    {
        return [
            'purchase_price' => 'decimal:2',
            'warranty_expires_at' => 'date',
        ];
    }

    protected static function booted(): void
    {
        static::creating(function (self $serial): void {
            if (! $serial->uuid) {
                $serial->uuid = Str::ulid();
            }
        });
    }

    // ── Relations ─────────────────────────────────────────────────────────────

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }

    public function batch(): BelongsTo
    {
        return $this->belongsTo(StockBatch::class, 'stock_batch_id');
    }

    public function currentCustomer(): BelongsTo
    {
        return $this->belongsTo(Customer::class, 'current_customer_id');
    }

    public function status(): BelongsTo
    {
        return $this->belongsTo(Status::class, 'status_id');
    }

    /** At most one — a serial is one physical item, so it wears one label. */
    public function barcodeLabel(): HasOne
    {
        return $this->hasOne(BarcodeLabel::class, 'product_serial_id');
    }

    public function ownershipHistory(): HasMany
    {
        return $this->hasMany(SerialOwnershipHistory::class, 'product_serial_id')->latest('occurred_at');
    }

    public function repairHistory(): HasMany
    {
        return $this->hasMany(SerialRepairHistory::class, 'product_serial_id')->latest('started_at');
    }

    // ── Scopes ────────────────────────────────────────────────────────────────

    public function scopeAvailable(Builder $query): void
    {
        $query->whereHas('status', fn ($q) => $q->whereIn('code', [
            Status::SERIAL_AVAILABLE,
            Status::SERIAL_IN_STOCK,
        ]));
    }

    public function scopeInBranch(Builder $query, int $branchId): void
    {
        $query->where('branch_id', $branchId);
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    public function isAvailable(): bool
    {
        return in_array($this->status?->code, [
            Status::SERIAL_AVAILABLE,
            Status::SERIAL_IN_STOCK,
        ], true);
    }

    public function isSold(): bool
    {
        return $this->status?->code === Status::SERIAL_SOLD;
    }
}
