<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Picqer\Barcode\BarcodeGeneratorPNG;

use Illuminate\Database\Eloquent\Factories\HasFactory;

class Product extends Model
{
    use SoftDeletes, HasFactory;

    protected $fillable = [
        'category_id',
        'name',
        'name_ar',
        'sku',
        'barcode',
        'description',
        'cost_price',
        'selling_price',
        'min_selling_price',
        'barcode_type',
        'is_repair_part',
        'is_service',
        'warranty_months',
        'linked_product_id',
        'unit_id',
        'volume',
        'track_inventory',
        'min_stock_level',
        'image',
        'is_active',
    ];

    protected $casts = [
        'cost_price' => 'decimal:2',
        'selling_price' => 'decimal:2',
        'min_selling_price' => 'decimal:2',
        'is_repair_part' => 'boolean',
        'track_inventory' => 'boolean',
        'is_active' => 'boolean',
    ];

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($product) {
            if (empty($product->sku)) {
                $product->sku = static::generateSku();
            }
            if (empty($product->barcode)) {
                $product->barcode = $product->sku;
            }
        });
    }

    /**
     * Generate a unique SKU
     */
    public static function generateSku(): string
    {
        $prefix = 'PRD';
        $number = str_pad(static::withTrashed()->count() + 1, 6, '0', STR_PAD_LEFT);
        return $prefix . $number;
    }

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

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

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

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

    /**
     * Alias for inventory - used by StockOverview
     */
    public function stocks(): HasMany
    {
        return $this->hasMany(ProductStock::class);
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeRepairParts($query)
    {
        return $query->where('is_repair_part', true);
    }

    public function scopeTracked($query)
    {
        return $query->where('track_inventory', true);
    }

    public function scopePhysical($query)
    {
        return $query->where('is_service', false);
    }

    public function scopeService($query)
    {
        return $query->where('is_service', true);
    }

    /**
     * Get stock quantity for a specific branch
     * Optionally filtered by specific locations
     */
    public function getStockForBranch(?int $branchId, array $locationIds = []): int
    {
        if (!$branchId) {
            return 0;
        }

        $query = $this->inventory()->where('branch_id', $branchId);

        if (!empty($locationIds)) {
            $query->whereIn('location_id', $locationIds);
        }

        return (int) $query->sum('quantity');
    }

    /**
     * Get total stock across all branches
     */
    public function getTotalStock(): int
    {
        return $this->inventory()->sum('quantity');
    }

    /**
     * Get localized name
     */
    public function getLocalizedNameAttribute(): string
    {
        $locale = app()->getLocale();
        
        if ($locale === 'ar' && !empty($this->name_ar)) {
            return $this->name_ar;
        }

        return $this->name;
    }

    /**
     * Check if stock is low
     */
    public function isLowStock(?int $branchId = null): bool
    {
        $stock = $branchId 
            ? $this->getStockForBranch($branchId) 
            : $this->getTotalStock();

        return $stock <= $this->min_stock_level;
    }

    /**
     * Generate barcode image as base64
     */
    public function generateBarcodeImage(): string
    {
        $generator = new BarcodeGeneratorPNG();
        $barcode = $generator->getBarcode(
            $this->barcode ?? $this->sku,
            $this->getBarcodeType()
        );
        
        return 'data:image/png;base64,' . base64_encode($barcode);
    }

    protected function getBarcodeType(): string
    {
        return match ($this->barcode_type) {
            'EAN13' => BarcodeGeneratorPNG::TYPE_EAN_13,
            'QR' => BarcodeGeneratorPNG::TYPE_CODE_128, // Fallback, as this library doesn't support QR
            default => BarcodeGeneratorPNG::TYPE_CODE_128,
        };
    }

    public function linkedProduct(): BelongsTo
    {
        return $this->belongsTo(Product::class, 'linked_product_id');
    }
}
