<?php

namespace App\Models;

use App\Models\Traits\HasAuditFields;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class SkuMaster extends Model
{
    use SoftDeletes, HasAuditFields;

    protected $table = 'skumaster';

    /**
     * Stock status constants
     */
    public const STOCK_IN = 'in_stock';
    public const STOCK_LOW = 'low_stock';
    public const STOCK_OUT = 'out_of_stock';

    protected $fillable = [
        'item_name',
        'category',
        'uom',
        'tax_rate',
        'current_stock',
        'default_price',
        'discount_price',
        'tcs',
        'min_order_level',
        'max_order_level',
        'hsn_code',
        'supplier_name',
        'supplier_phone',
        'supplier_email',
        'reason',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'tax_rate' => 'decimal:2',
        'current_stock' => 'decimal:2',
        'default_price' => 'decimal:2',
        'discount_price' => 'decimal:2',
        'tcs' => 'decimal:2',
        'min_order_level' => 'integer',
        'max_order_level' => 'integer',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    // ──────────────────────────────────────────────────────────────────────────
    // RELATIONSHIPS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Get all movements for this SKU.
     */
    public function movements()
    {
        return $this->hasMany(SkuMovement::class, 'sku_id');
    }

    /**
     * Get inbound movements.
     */
    public function inboundMovements()
    {
        return $this->movements()->where('type', SkuMovement::TYPE_INBOUND);
    }

    /**
     * Get outbound movements.
     */
    public function outboundMovements()
    {
        return $this->movements()->where('type', SkuMovement::TYPE_OUTBOUND);
    }

    /**
     * Get the user who created this SKU.
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    // ──────────────────────────────────────────────────────────────────────────
    // SCOPES
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Filter in stock items
     */
    public function scopeInStock(Builder $query): Builder
    {
        return $query->where('current_stock', '>', 0);
    }

    /**
     * Filter out of stock items
     */
    public function scopeOutOfStock(Builder $query): Builder
    {
        return $query->where('current_stock', '<=', 0);
    }

    /**
     * Filter low stock items (below minimum order level)
     */
    public function scopeLowStock(Builder $query): Builder
    {
        return $query->whereColumn('current_stock', '<=', 'min_order_level')
                     ->where('current_stock', '>', 0);
    }

    /**
     * Filter items needing reorder
     */
    public function scopeNeedsReorder(Builder $query): Builder
    {
        return $query->whereColumn('current_stock', '<=', 'min_order_level');
    }

    /**
     * Filter by category
     */
    public function scopeInCategory(Builder $query, string $category): Builder
    {
        return $query->where('category', $category);
    }

    /**
     * Search by name or HSN code
     */
    public function scopeSearch(Builder $query, string $term): Builder
    {
        return $query->where(function ($q) use ($term) {
            $q->where('item_name', 'LIKE', "%{$term}%")
              ->orWhere('hsn_code', 'LIKE', "%{$term}%")
              ->orWhere('category', 'LIKE', "%{$term}%");
        });
    }

    /**
     * Filter by supplier
     */
    public function scopeBySupplier(Builder $query, string $supplierName): Builder
    {
        return $query->where('supplier_name', 'LIKE', "%{$supplierName}%");
    }

    // ──────────────────────────────────────────────────────────────────────────
    // ACCESSORS & HELPERS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Get stock status
     */
    public function getStockStatus(): string
    {
        if ($this->current_stock <= 0) {
            return self::STOCK_OUT;
        }

        if ($this->current_stock <= $this->min_order_level) {
            return self::STOCK_LOW;
        }

        return self::STOCK_IN;
    }

    /**
     * Get stock status label
     */
    public function getStockStatusLabel(): string
    {
        return match($this->getStockStatus()) {
            self::STOCK_IN => 'In Stock',
            self::STOCK_LOW => 'Low Stock',
            self::STOCK_OUT => 'Out of Stock',
            default => 'Unknown',
        };
    }

    /**
     * Check if in stock
     */
    public function isInStock(): bool
    {
        return $this->current_stock > 0;
    }

    /**
     * Check if low stock
     */
    public function isLowStock(): bool
    {
        return $this->current_stock > 0 && $this->current_stock <= $this->min_order_level;
    }

    /**
     * Check if out of stock
     */
    public function isOutOfStock(): bool
    {
        return $this->current_stock <= 0;
    }

    /**
     * Check if needs reorder
     */
    public function needsReorder(): bool
    {
        return $this->current_stock <= $this->min_order_level;
    }

    /**
     * Get reorder quantity
     */
    public function getReorderQuantity(): float
    {
        if (!$this->needsReorder()) {
            return 0;
        }

        return max(0, $this->max_order_level - $this->current_stock);
    }

    /**
     * Add stock (creates movement record)
     */
    public function addStock(float $quantity, string $reference = null, string $notes = null): SkuMovement
    {
        $this->increment('current_stock', $quantity);

        return $this->movements()->create([
            'type' => SkuMovement::TYPE_INBOUND,
            'quantity' => $quantity,
            'reference' => $reference ?? 'STOCK-ADD-' . now()->format('YmdHis'),
            'product' => $this->item_name,
            'to_location' => 'Inventory',
            'date' => now(),
            'status' => SkuMovement::STATUS_COMPLETED,
            'notes' => $notes,
            'created_by' => auth()->id(),
        ]);
    }

    /**
     * Deduct stock (creates movement record)
     */
    public function deductStock(float $quantity, string $reference = null, string $notes = null): ?SkuMovement
    {
        if ($this->current_stock < $quantity) {
            return null; // Insufficient stock
        }

        $this->decrement('current_stock', $quantity);

        return $this->movements()->create([
            'type' => SkuMovement::TYPE_OUTBOUND,
            'quantity' => $quantity,
            'reference' => $reference ?? 'STOCK-DEDUCT-' . now()->format('YmdHis'),
            'product' => $this->item_name,
            'from_location' => 'Inventory',
            'date' => now(),
            'status' => SkuMovement::STATUS_COMPLETED,
            'notes' => $notes,
            'created_by' => auth()->id(),
        ]);
    }

    /**
     * Get price with tax
     */
    public function getPriceWithTax(): float
    {
        $price = $this->discount_price ?? $this->default_price;
        $taxAmount = $price * ($this->tax_rate / 100);
        return $price + $taxAmount;
    }
}
