<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

#[Fillable(['category_id', 'name', 'slug', 'description', 'price', 'purchase_price', 'discount_percent', 'fake_discount_percent', 'stock', 'rating', 'youtube_url', 'meta_title', 'meta_description', 'og_image_path', 'is_active', 'is_featured'])]
class Product extends Model
{
    protected function casts(): array
    {
        return [
            'price' => 'decimal:2',
            'purchase_price' => 'decimal:2',
            'discount_percent' => 'decimal:2',
            'fake_discount_percent' => 'decimal:2',
            'rating' => 'decimal:1',
            'is_active' => 'boolean',
            'is_featured' => 'boolean',
        ];
    }

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

    public function images(): HasMany
    {
        return $this->hasMany(ProductImage::class)->orderBy('sort_order');
    }

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

    public function activeVariants(): HasMany
    {
        return $this->variants()->where('is_active', true)->orderBy('name')->orderBy('value');
    }

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

    public function inventoryMovements(): HasMany
    {
        return $this->hasMany(InventoryMovement::class)->latest();
    }

    public function primaryImageUrl(): ?string
    {
        $image = $this->images->first();

        return $image?->url();
    }

    public function ogImageUrl(): ?string
    {
        return \App\Support\PublicStorage::url($this->og_image_path);
    }

    public function basePrice(): float
    {
        return (float) $this->price;
    }

    public function realDiscountPercent(): float
    {
        return max(0, min(100, (float) $this->discount_percent));
    }

    public function fakeDiscountPercent(): float
    {
        return max(0, min(100, (float) $this->fake_discount_percent));
    }

    public function sellingPrice(?float $basePrice = null): float
    {
        $price = $basePrice ?? $this->basePrice();

        return round($price * (1 - ($this->realDiscountPercent() / 100)), 2);
    }

    public function compareAtPrice(?float $basePrice = null): ?float
    {
        $price = $basePrice ?? $this->basePrice();

        if ($this->fakeDiscountPercent() > 0) {
            return round($price * (1 + ($this->fakeDiscountPercent() / 100)), 2);
        }

        if ($this->realDiscountPercent() > 0) {
            return $price;
        }

        return null;
    }

    public function displayDiscountPercent(): float
    {
        return min(100, $this->realDiscountPercent() + $this->fakeDiscountPercent());
    }
}
