<?php

namespace Modules\SystemCore\App\Models;

use App\Traits\UserActionsTrait;
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\Database\Eloquent\SoftDeletes;
use Modules\SystemCore\App\Enums\ProductStatus;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;

class CoreProduct extends Model implements AuditableContract
{
    use Auditable, HasFactory, SoftDeletes, UserActionsTrait;

    protected $table = 'core_products';

    protected $fillable = [
        'product_code',
        'sku',
        'barcode',
        'name',
        'description',
        'category_id',
        'brand',
        'status',
        'unit_of_measure',
        'base_price',
        'cost_price',
        'selling_price',
        'tax_id',
        'weight',
        'weight_unit',
        'dimensions',
        'min_stock_level',
        'max_stock_level',
        'reorder_level',
        'images',
        'thumbnail',
        'tags',
        'metadata',
        'is_active',
        'is_trackable',
        'has_variants',
        'created_by_id',
        'updated_by_id',
    ];

    protected function casts(): array
    {
        return [
            'status' => ProductStatus::class,
            'base_price' => 'decimal:2',
            'cost_price' => 'decimal:2',
            'selling_price' => 'decimal:2',
            'weight' => 'decimal:2',
            'min_stock_level' => 'integer',
            'max_stock_level' => 'integer',
            'reorder_level' => 'integer',
            'dimensions' => 'array',
            'images' => 'array',
            'tags' => 'array',
            'metadata' => 'array',
            'is_active' => 'boolean',
            'is_trackable' => 'boolean',
            'has_variants' => 'boolean',
        ];
    }

    /**
     * Get category
     */
    public function category(): BelongsTo
    {
        return $this->belongsTo(CoreProductCategory::class, 'category_id');
    }

    /**
     * Get tax configuration
     */
    public function taxConfiguration(): BelongsTo
    {
        return $this->belongsTo(CoreTaxConfiguration::class, 'tax_id');
    }

    /**
     * Alias for taxConfiguration (for backwards compatibility)
     */
    public function tax(): BelongsTo
    {
        return $this->taxConfiguration();
    }

    /**
     * Get product variants
     */
    public function variants(): HasMany
    {
        return $this->hasMany(CoreProductVariant::class, 'product_id');
    }

    /**
     * Get pricing rules
     */
    public function pricingRules(): HasMany
    {
        return $this->hasMany(CorePricingRule::class, 'product_id');
    }

    /**
     * Get WMS inventory records (requires WMSInventoryCore module)
     */
    public function inventories(): HasMany
    {
        $inventoryClass = '\\Modules\\WMSInventoryCore\\App\\Models\\Inventory';
        if (moduleExists('WMSInventoryCore') && class_exists($inventoryClass)) {
            return $this->hasMany($inventoryClass, 'core_product_id');
        }

        // Return empty relation when WMSInventoryCore is not available
        return $this->hasMany(CoreProductVariant::class, 'product_id')->whereRaw('1=0');
    }

    /**
     * Scope for active products
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true)
            ->where('status', ProductStatus::Active);
    }

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

    /**
     * Generate product code using settings
     */
    public static function generateProductCode(): string
    {
        $settingsService = app(\App\Services\Settings\ModuleSettingsService::class);
        $prefix = $settingsService->get('SystemCore', 'product_prefix', 'PROD');
        $padding = (int) $settingsService->get('SystemCore', 'product_code_padding', 6);

        $lastProduct = self::orderBy('id', 'desc')->first();
        $nextId = $lastProduct ? $lastProduct->id + 1 : 1;

        return $prefix.'-'.str_pad((string) $nextId, $padding, '0', STR_PAD_LEFT);
    }

    /**
     * Boot method
     */
    protected static function booted()
    {
        static::creating(function (CoreProduct $product) {
            if (! $product->product_code) {
                $product->product_code = self::generateProductCode();
            }
        });
    }
}
