<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use App\Models\Concerns\LogsActivity;

class Product extends Model implements HasMedia
{
    use InteractsWithMedia, LogsActivity;

    public function getActivityLogDescription(string $action): string
    {
        return sprintf('Product "%s" (%s) %s', $this->name, $this->sku, $action);
    }

    protected $fillable = [
        'category_id',
        'brand_id',
        'name',
        'slug',
        'description',
        'short_description',
        'sku',
        'price',
        'sale_price',
        'quantity',
        'is_visible',
        'is_featured',
        'seo_title',
        'seo_description',
        'compare_at_price',
        'cost_price',
        'barcode',
        'security_stock',
        'published_at',
        'can_be_returned',
        'will_be_shipped',
        'weight_grams',
        'is_weight_based',
        'external_id',
    ];

    protected $casts = [
        'price' => 'decimal:2',
        'sale_price' => 'decimal:2',
        'compare_at_price' => 'decimal:2',
        'cost_price' => 'decimal:2',
        'quantity' => 'integer',
        'security_stock' => 'integer',
        'is_visible' => 'boolean',
        'is_featured' => 'boolean',
        'can_be_returned'  => 'boolean',
        'will_be_shipped'  => 'boolean',
        'published_at'     => 'date',
        'weight_grams'     => 'integer',
        'is_weight_based'  => 'boolean',
    ];

    protected $appends = ['reseller_price'];

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

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

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

    public function reviews(): HasMany
    {
        return $this->hasMany(ProductReview::class)->where('status', 'approved');
    }

    /**
     * Spatie Media Collections configuration
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('images')
            ->useFallbackUrl('/images/placeholder.jpg')
            ->useFallbackPath(public_path('/images/placeholder.jpg'));
    }

    public function registerMediaConversions(?\Spatie\MediaLibrary\MediaCollections\Models\Media $media = null): void
    {
        $this->addMediaConversion('webp')
            ->format('webp')
            ->quality(80)
            ->nonQueued();
    }

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

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

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

    /**
     * Get the effective (selling) price of the product.
     * Admin panel uses "Price" as the current selling price and "Compare at price" as the
     * original/crossed-out price. sale_price is legacy and not shown in the admin form.
     */
    public function getEffectivePriceAttribute(): float
    {
        return (float) $this->price;
    }

    /**
     * Generate a unique SKU based on the product name.
     */
    public static function generateUniqueSku(string $name): string
    {
        $words = explode(' ', preg_replace('/[^a-zA-Z0-9\s]/', '', $name));
        $prefix = '';
        if (count($words) >= 2) {
            foreach ($words as $word) {
                if (!empty($word)) {
                    $prefix .= strtoupper($word[0]);
                }
            }
        } else {
            $prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', $name), 0, 4));
        }

        $prefix = substr($prefix, 0, 5);
        if (empty($prefix)) {
            $prefix = 'PROD';
        }

        do {
            $number = str_pad(random_int(1000, 9999), 4, '0', STR_PAD_LEFT);
            $sku = "{$prefix}-{$number}";
        } while (static::where('sku', $sku)->exists());

        return $sku;
    }

    /**
     * Get the calculated reseller price (cost_price + 15%).
     */
    public function getResellerPriceAttribute(): float
    {
        $cost = (float) ($this->cost_price ?? 0);
        if ($cost <= 0) {
            return round($this->price * 0.85, 2);
        }
        return round($cost * 1.15, 2);
    }

    protected static function booted()
    {
        static::saved(function ($product) {
            \Illuminate\Support\Facades\Cache::forget('home_data_payload');
            \Illuminate\Support\Facades\Cache::forget('site_settings_compiled');
            \Illuminate\Support\Facades\Cache::forget('categories_list');
            \Illuminate\Support\Facades\Cache::forget('product_detail_' . $product->id);
            if ($product->slug) {
                \Illuminate\Support\Facades\Cache::forget('product_detail_' . $product->slug);
            }
        });

        static::deleted(function ($product) {
            \Illuminate\Support\Facades\Cache::forget('home_data_payload');
            \Illuminate\Support\Facades\Cache::forget('site_settings_compiled');
            \Illuminate\Support\Facades\Cache::forget('categories_list');
            \Illuminate\Support\Facades\Cache::forget('product_detail_' . $product->id);
            if ($product->slug) {
                \Illuminate\Support\Facades\Cache::forget('product_detail_' . $product->slug);
            }
        });
    }
}

