<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Enums\BookingItemStatus;
use App\Enums\BookingStatus;
use App\Models\Review;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

class Product extends Model  implements HasMedia
{
    use HasFactory, SoftDeletes, InteractsWithMedia;

    protected $fillable = [
        'service_provider_id',
        'category_id',
        'type',
        'name_en',
        'name_ar',
        'description_en',
        'description_ar',
        'details_en',
        'details_ar',
        'price',
        'price_before_discount',
        'location_url',
        'is_active',
    ];

    protected $casts = [
        'is_active' => 'boolean',
        'price' => 'float',
        'price_before_discount' => "float",
    ];

    protected $with = ['bookedItems', 'availabilities'];

    protected $appends = ['avg_rating', 'booked_dates'];

    public function getBookedDatesAttribute()
    {
        $bookings = $this->bookedItems
            ?->pluck('service_date')->toArray();

        return array_values($bookings);
    }

    public function getNotAvailableDatesAttribute()
    {
        return $this->availabilities?->pluck('date')->toArray();
    }

    public function getNameAttribute()
    {
        $locale = app()->getLocale();
        return $locale === 'ar' ? $this->name_ar : $this->name_en;
    }

    public function getAllBlockedDatesAttribute()
    {
        $bookings = $this->getBookedDatesAttribute();
        $availabilities = $this->getNotAvailableDatesAttribute();

        return array_unique(array_merge($bookings, $availabilities));
    }

    public function getAvgRatingAttribute()
    {
        // round to 2 decimal places
        return round($this->reviews()->avg('rating') ?? 0, 2);
    }

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

    public function scopeAvailable($query)
    {
        return $query
            ->active()
            ->hasActiveServiceProvider()
            ->hasActiveCity()
            ->where(function ($q) {
                $q->where('type', 'package')
                    ->orWhere(function ($q) {
                        $q->where('type', 'service')->hasActiveCategory();
                    });
            });
    }

    public function scopeHasActiveServiceProvider($query)
    {
        return $query->whereHas('serviceProvider', function ($q) {
            $q->where('is_active', true);
        });
    }

    public function scopeHasActiveCategory($query)
    {
        return $query->whereHas('category', function ($q) {
            $q->where('is_active', true);
        });
    }

    public function scopeHasActiveCity($query)
    {
        return $query->whereHas('cities', function ($q) {
            $q->where('is_active', true);
        });
    }


    public function serviceProvider()
    {
        return $this->belongsTo(ServiceProvider::class);
    }

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

    public function cities()
    {
        return $this->belongsToMany(City::class, 'city_product');
    }

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

    public function availabilities()
    {
        return $this->hasMany(ProductAvailability::class);
    }

    public function bookingItems()
    {
        return $this->hasMany(BookingItem::class);
    }

    public function bookedItems()
    {
        return $this->hasMany(BookingItem::class)
            ->whereNotIn('status', [BookingItemStatus::DECLINED, BookingItemStatus::CANCELED])
            ->whereHas("booking", function ($query) {
                $query->whereNot("status",  BookingStatus::CANCELED);
            });
    }

    // clear media after deletion
    protected static function booted()
    {
        static::deleted(function ($product) {
            $product->clearMediaCollection('images');
            $product->clearMediaCollection('videos');
        });

        static::deleting(function ($product) {
            $product->is_active = false;
        });
    }
}
