<?php

namespace App\Models;

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

class Product extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'slug',
        'description',
        'price',
        'image',
        'stock',
        'is_active',
        'upc',
        'sku',
        'asin',
        'manufacturer',
        'moq',
        'meta_description',
        'meta_title',
        'meta_keywords',
        'meta_tags',
        'page_schemas',
        'category_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'price' => 'decimal:2',
        'stock' => 'integer',
        'is_active' => 'boolean',
        'moq' => 'integer',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'created_at',
        'updated_at',
    ];

    /**
     * Boot function for automatic slug generation.
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($product) {
            if (empty($product->slug)) {
                $product->slug = Str::slug($product->name);
            }
        });

        static::updating(function ($product) {
            if ($product->isDirty('name') && empty($product->slug)) {
                $product->slug = Str::slug($product->name);
            }
        });
    }

    /**
     * Get the category that owns the product.
     */
    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }
    public function leads()
    {
        return $this->hasMany(Lead::class);
    }



    

    /**
     * Scope a query to only include active products.
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope a query to only include products in stock.
     */
    public function scopeInStock($query)
    {
        return $query->where('stock', '>', 0);
    }

    /**
     * Scope a query to search products.
     */
    public function scopeSearch($query, $search)
    {
        return $query->where(function ($q) use ($search) {
            $q->where('name', 'like', "%{$search}%")
              ->orWhere('description', 'like', "%{$search}%")
              ->orWhere('sku', 'like', "%{$search}%")
              ->orWhere('upc', 'like', "%{$search}%")
              ->orWhere('asin', 'like', "%{$search}%")
              ->orWhere('manufacturer', 'like', "%{$search}%");
        });
    }

    /**
     * Scope a query to filter by category.
     */
    public function scopeByCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }

    

    /**
     * Check if product is in stock.
     */
    public function getIsInStockAttribute(): bool
    {
        return $this->stock > 0;
    }

    /**
     * Check if product is low stock.
     */
    public function getIsLowStockAttribute(): bool
    {
        return $this->stock > 0 && $this->stock <= 10;
    }

    /**
     * Check if product is out of stock.
     */
    public function getIsOutOfStockAttribute(): bool
    {
        return $this->stock === 0;
    }

    /**
     * Get formatted price.
     */
    public function getFormattedPriceAttribute(): string
    {
        return '$' . number_format($this->price, 2);
    }

    /**
     * Get stock status.
     */
    public function getStockStatusAttribute(): string
    {
        if ($this->stock === 0) {
            return 'Out of Stock';
        } elseif ($this->stock <= 10) {
            return 'Low Stock';
        } else {
            return 'In Stock';
        }
    }

    /**
     * Get stock status color.
     */
    public function getStockStatusColorAttribute(): string
    {
        if ($this->stock === 0) {
            return 'red';
        } elseif ($this->stock <= 10) {
            return 'yellow';
        } else {
            return 'green';
        }
    }

    /**
     * Get the route key for the model.
     */
    public function getRouteKeyName(): string
    {
        return 'slug';
    }

    /**
     * Generate unique SKU if not provided.
     */
    public function generateSku(): string
    {
        if (!empty($this->sku)) {
            return $this->sku;
        }

        $prefix = strtoupper(substr($this->name, 0, 3));
        $random = strtoupper(Str::random(6));
        
        return $prefix . '-' . $random;
    }

    /**
     * Decrement stock quantity.
     */
    public function decrementStock(int $quantity = 1): bool
    {
        if ($this->stock < $quantity) {
            return false;
        }

        $this->decrement('stock', $quantity);
        return true;
    }

    /**
     * Increment stock quantity.
     */
    public function incrementStock(int $quantity = 1): bool
    {
        $this->increment('stock', $quantity);
        return true;
    }

    /**
     * Check if product meets MOQ (Minimum Order Quantity).
     */
    public function meetsMoq(int $quantity): bool
    {
        if (empty($this->moq)) {
            return true;
        }

        return $quantity >= $this->moq;
    }

    /**
     * Get related products (same category).
     */
    public function relatedProducts(int $limit = 4)
    {
        if (!$this->category_id) {
            return collect();
        }

        return self::active()
            ->where('category_id', $this->category_id)
            ->where('id', '!=', $this->id)
            ->limit($limit)
            ->get();
    }

    /**
     * Get SEO meta data as array.
     */
    public function getSeoMetaAttribute(): array
    {
        return [
            'title' => $this->meta_title ?: $this->name,
            'description' => $this->meta_description ?: Str::limit(strip_tags($this->description), 160),
            'keywords' => $this->meta_keywords,
            'tags' => $this->meta_tags,
            'schemas' => $this->page_schemas ? json_decode($this->page_schemas, true) : null,
        ];
    }
}