<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

class Product extends Model
{
    use \Illuminate\Database\Eloquent\SoftDeletes;

    protected $guarded = [];

    const STATUS_INACTIVE = 0;

    const STATUS_ACTIVE = 1;

    const CURRENCY = 'CDF';

    public const STOCK_STATUSES = [
        ['id' => 'in_stock', 'name' => 'Stock disponible', 'slug' => 'in_stock'],
        ['id' => 'low_stock', 'name' => 'Stock faible', 'slug' => 'low_stock'],
        ['id' => 'out_of_stock', 'name' => 'Rupture de stock', 'slug' => 'out_of_stock'],
    ];

    public const STATUS_LABELS = [
        ['id' => self::STATUS_INACTIVE, 'name' => 'Inactif', 'slug' => 'inactif'],
        ['id' => self::STATUS_ACTIVE, 'name' => 'Actif', 'slug' => 'actif'],
    ];

    protected $casts = [
        'selling_price' => 'decimal:2',
        'purchase_price' => 'decimal:2',
        'current_stock' => 'integer',
        'reorder_level' => 'integer',
        'is_active' => 'boolean',
    ];

    public function getRouteKeyName()
    {
        return 'slug';
    }

    public static function generateUniqueSlug()
    {
        $slug = Str::orderedUuid();
        $count = self::where('slug', 'like', "{$slug}%")->count();
        if ($count > 0) {
            $slug .= '-'.($count + 1);
        }

        return $slug;
    }

    public static function generateUniqueSKU(?string $name = null): string
    {
        // Generate SKU based on product name prefix + timestamp + random number
        $prefix = 'SKU';

        if ($name) {
            // Take first 3 letters from product name
            $namePrefix = strtoupper(substr(preg_replace('/[^A-Za-z]/', '', $name), 0, 3));
            if (! empty($namePrefix)) {
                $prefix = $namePrefix;
            }
        }

        // Generate unique SKU
        do {
            $sku = $prefix.'-'.date('Ymd').'-'.str_pad(mt_rand(1, 999), 3, '0', STR_PAD_LEFT);
        } while (self::where('sku', $sku)->exists());

        return $sku;
    }

    public function purchaseUnit(): BelongsTo
    {
        return $this->belongsTo(Unit::class, 'purchase_unit_id');
    }

    public function saleUnit(): BelongsTo
    {
        return $this->belongsTo(Unit::class, 'sale_unit_id');
    }

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

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

    public function locations(): BelongsToMany
    {
        return $this->belongsToMany(Location::class, 'location_product')
            ->withPivot(['quantity'])
            ->withTimestamps();
    }

    public function saleItems(): HasMany
    {
        return $this->hasMany(SaleItem::class);
    }

    public function sales()
    {
        return $this->hasManyThrough(Sale::class, SaleItem::class, 'product_id', 'id', 'id', 'sale_id');
    }

    public function stockEntries(): HasMany
    {
        return $this->hasMany(StockEntry::class);
    }

    public function getStatusBadge()
    {
        if ($this->status == self::STATUS_ACTIVE) {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 border border-green-500 min-w-30 justify-center">
                <i class="ph ph-check-circle mr-1"></i>
                Actif
            </span>';
        } else {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 border border-red-500 min-w-30 justify-center">
                <i class="ph ph-x-circle mr-1"></i>
                Inactif
            </span>';
        }
    }

    public function getStockStatusBadge()
    {
        if ($this->current_stock > 0 && $this->current_stock >= $this->reorder_level) {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 border border-green-500 min-w-30 justify-center">
                <i class="ph ph-check-circle mr-1"></i>
                Suffisant
            </span>';
        } elseif ($this->current_stock > 0 && $this->current_stock <= $this->reorder_level) {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800 border border-yellow-500 min-w-30 justify-center">
                <i class="ph ph-warning mr-1"></i>
                Faible
            </span>';
        } else {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 border border-red-500 min-w-30 justify-center">
                <i class="ph ph-warning mr-1"></i>
                Rupture de stock
            </span>';
        }
    }

    public function getStockQuantityBadge()
    {
        if ($this->current_stock > 0 && $this->current_stock >= $this->reorder_level) {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 border border-green-500 min-w-30 justify-center">
                '.$this->current_stock.' '.Str::plural($this->saleUnit->name ?? 'unité', $this->current_stock).'
            </span>';
        } elseif ($this->current_stock > 0 && $this->current_stock <= $this->reorder_level) {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800 border border-yellow-500 min-w-30 justify-center">
                '.$this->current_stock.' '.Str::plural($this->saleUnit->name ?? 'unité', $this->current_stock).'
            </span>';
        } else {
            return '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 border border-red-500 min-w-30 justify-center">
                '.$this->current_stock.' '.Str::plural($this->saleUnit->name ?? 'unité', $this->current_stock).'
            </span>';
        }
    }

    public function getStockStatus()
    {
        $reorder_level = $this->reorder_level;
        $current_stock = $this->current_stock;

        if ($current_stock > $reorder_level) {
            return (object) self::STOCK_STATUSES[0];
        }
        if ($current_stock > 0 && $current_stock <= $reorder_level) {
            return (object) self::STOCK_STATUSES[1];
        }

        return (object) self::STOCK_STATUSES[2];
    }

    // Unit Conversion Methods
    public function getPurchaseStock(): float
    {
        // Convert sale units to purchase units
        return $this->current_stock / $this->conversion_factor;
    }

    public function getSaleStock(): int
    {
        // Return current stock in sale units
        return $this->current_stock;
    }

    public function getPricePerSaleUnit(): float
    {
        // Calculate price per sale unit from purchase price
        if ($this->purchase_price && $this->conversion_factor > 0) {
            return $this->purchase_price / $this->conversion_factor;
        }

        return $this->selling_price ?? 0;
    }

    public function getPricePerPurchaseUnit(): float
    {
        // Calculate price per purchase unit from sale price
        if ($this->selling_price && $this->conversion_factor > 0) {
            return $this->selling_price * $this->conversion_factor;
        }

        return $this->purchase_price ?? 0;
    }

    public function getFormattedConversion(): string
    {
        if ($this->purchaseUnit && $this->saleUnit && $this->conversion_factor > 1) {
            return "1 {$this->purchaseUnit->name} = {$this->conversion_factor} {$this->saleUnit->name}";
        }

        return '1 '.($this->saleUnit ? $this->saleUnit->name : 'unité');
    }

    public function hasAllRequiredFields(): array
    {
        $requiredFields = [
            ['name', 'nom'],
            ['category_id', 'catégorie'],
            ['purchase_unit_id', 'unité d\'achat'],
            ['purchase_price', 'prix d\'achat'],
            ['sale_unit_id', 'unité de vente'],
            ['selling_price', 'prix de vente'],
            ['conversion_factor', 'facteur de conversion'],
            ['reorder_level', 'niveau de réapprovisionnement'],
        ];

        $missing = [];

        foreach ($requiredFields as $field) {
            [$key, $label] = $field;
            $value = $this->{$key};

            // Treat null/empty string as missing; allow 0/0.00 for numeric fields if desired
            $isMissing = is_null($value) || (is_string($value) && trim($value) === '');

            if ($isMissing) {
                $missing[] = $label;
            }
        }

        if (! empty($missing)) {
            return ['success' => false, 'message' => 'Champs requis manquants: '.implode(', ', $missing)];
        }

        return ['success' => true, 'message' => 'Tous les champs requis sont remplis'];
    }
}
