<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Laravel\Scout\Searchable;

class Product extends Model
{
    use HasFactory, Searchable;

    protected $guarded = ['id', 'created_at', 'updated_at'];

    protected function casts(): array
    {
        return [
            'category_id' => 'integer',
            'price' => 'decimal:2',
            'discount_price' => 'decimal:2',
            'discount' => 'decimal:2',
            'clicks' => 'integer',
            'direct_commission_rate' => 'decimal:2',
            'estimated_direct_commission' => 'decimal:2',
            'indirect_commission_rate' => 'decimal:2',
            'estimated_indirect_commission' => 'decimal:2',
            'sales_180day' => 'integer',
            'positive_feedback' => 'decimal:2',
            'code_start_time' => 'datetime',
            'code_end_time' => 'datetime',
            'code_quantity' => 'integer',
            'code_minimum_spend' => 'decimal:2',
        ];
    }

    /**
     * Get the discount percentage as a calculated attribute.
     */
    protected function discount(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->discount_price && $this->price
                ? round((($this->price - $this->discount_price) / $this->price) * 100, 2)
                : 0
        );
    }

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

    public function scopeFilterByCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }

    public function scopeFilterByPriceRange($query, $minPrice = null, $maxPrice = null)
    {
        if ($minPrice !== null) {
            $query->where('price', '>=', $minPrice);
        }
        if ($maxPrice !== null) {
            $query->where('price', '<=', $maxPrice);
        }

        return $query;
    }

    public function scopeSearch($query, $searchTerm)
    {
        return $query->where(function ($q) use ($searchTerm) {
            $q->where('name_ar', 'like', "%{$searchTerm}%")
                ->orWhere('name_en', 'like', "%{$searchTerm}%");
        });
    }

    public function scopeSortBy($query, $field, $direction = 'asc')
    {
        $allowedFields = ['price', 'discount_price', 'clicks', 'sales_180day', 'positive_feedback'];

        if (in_array($field, $allowedFields)) {
            return $query->orderBy($field, $direction);
        }

        return $query;
    }

    public function scopeWhereHasDiscount($query)
    {
        return $query->whereNotNull('discount_price')
            ->whereColumn('discount_price', '<', 'price');
    }

    public function scopeOrderByDiscount($query, $direction = 'desc')
    {
        return $query->orderByRaw('(price - COALESCE(discount_price, price)) / price * 100 '.$direction);
    }

    /**
     * Get the indexable data array for the model.
     *
     * @return array<string, mixed>
     */
    public function toSearchableArray(): array
    {
        return [
            'id' => (int) $this->id,
            'name_ar' => (string) $this->name_ar,
            'name_en' => (string) $this->name_en,
            'description_ar' => $this->description_ar ?: '',
            'description_en' => $this->description_en ?: '',
            'price' => (float) $this->price,
            'discount_price' => $this->discount_price ? (float) $this->discount_price : null,
            'category_id' => (int) $this->category_id,
            'source' => $this->source ?: null,
            'sales_180day' => (int) ($this->sales_180day ?? 0),
            'clicks' => (int) ($this->clicks ?? 0),
        ];
    }

    /**
     * Get the Scout engine index name for the model.
     */
    public function searchableAs(): string
    {
        return 'products_index';
    }

    /**
     * Get the Meilisearch settings for the model.
     *
     * @return array<string, mixed>
     */
    public function meilisearchSettings(): array
    {
        return [
            'searchableAttributes' => [
                'name_en',
                'name_ar',
                'description_en',
                'description_ar',
            ],
            'filterableAttributes' => [
                'category_id',
                'price',
                'discount_price',
                'sales_180day',
                'positive_feedback',
                'source',
            ],
            'sortableAttributes' => [
                'price',
                'sales_180day',
                'clicks',
                'positive_feedback',
            ],
            'rankingRules' => [
                'words',
                'typo',
                'proximity',
                'attribute',
                'sort',
                'exactness',
                'sales_180day:desc',
                'positive_feedback:desc',
            ],
            'displayedAttributes' => [
                'id',
                'name_en',
                'name_ar',
                'description_en',
                'description_ar',
                'price',
                'discount_price',
                'category_id',
                'sales_180day',
                'clicks',
                'positive_feedback',
                'source',
            ],
        ];
    }
}
