<?php

namespace App\Models;

use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Support\Collection;

class MealPackage extends Model
{
    use HasFactory;

    protected $fillable = [
        'sort_order',
        'title',
        'description',
        'price',
        'currency',
        'scope',
        'tag',
        'is_icon',
        'icon_value',
        'is_allow_select_days',
        'is_variant',
        'default_availability',
        'is_published',

    ];

    protected $casts = [
        'is_icon' => 'boolean',
        'is_allow_select_days' => 'boolean',
        'is_variant' => 'boolean',
        'default_availability' => 'boolean',
        'is_published' => 'boolean',
    ];

    protected $appends = ['available_dates'];

    // Images (polymorphic)
    public function images(): MorphToMany
    {
        return $this->morphToMany(Image::class, 'imageable')
            ->withPivot('role', 'sort_order')
            ->withTimestamps()
            ->orderBy('imageables.sort_order');
    }

    // Availability rules (polymorphic)
    public function availabilityRules(): MorphMany
    {
        return $this->morphMany(AvailabilityRule::class, 'available');
    }

    // auto delte rules
    protected static function booted()
    {
        static::deleting(function ($mealPackage) {
            $mealPackage->availabilityRules()->delete();
        });
    }


    // Variants
    public function variants()
    {
        return $this->hasMany(MealPackageVariant::class);
    }

    // Rooms (many-to-many)
    public function rooms()
    {
        return $this->belongsToMany(Room::class, 'meal_package_room');
    }

    // Categories (many-to-many)
    public function roomCategories()
    {
        return $this->belongsToMany(RoomCategory::class, 'meal_package_room_category');
    }


    public function getAvailableDatesAttribute()
    {
        return $this->attributes['available_dates'] ?? collect();
    }

    // Helper to set available dates
    public function setAvailableDates(array|Collection $dates)
    {
        $this->available_dates = $dates;
        return $this;
    }


    // // ------------------------------------------------------< Check Availability of of item 
    // // 01 - get the item (meal package/addon/ or its varinat) with default state
    // // 02 - filter the rule acording to the defautl state -> if:1 only blocked, else: active
    // // 03 - check the rule is in valid period
    // // 04 - check each pattern wiht check and checkout date and get reustls
    // // 05 - and if
    // public function checkAvailability(string $checkIn, string $checkOut, $parentDefault = null): bool
    // {
    //     $available = $item->default_availability ?? ($parentDefault ?? false);

    //     $this->relationLoaded('availabilityRules');

    //     dump([
    //         'title' => $this->title,
    //         'in' => $checkIn,
    //         'out' => $checkOut,
    //         'available' => $this->availabilityRules,
    //         'rules' => $this->av,
    //         'item' => $this,
    //     ]);


    //     dump("Default active:",  $available);

    //     foreach ($this->availabilityRules as $rule) {

    //         dump("Rule:", $rule->pattern_type, $rule->rule_mode);
    //     }

    //     dump("SERVICE RESULT:", $available);

    //     return $available;
    // }




    // public function isAvailableForDates($checkIn, $checkOut)
    // {
    //     $checkIn = Carbon::parse($checkIn);
    //     $checkOut = Carbon::parse($checkOut);

    //     // Start with default_availability
    //     $available = $this->default_availability ?? false;

    //     foreach ($this->availabilityRules as $rule) {

    //         // Skip rules outside validity period
    //         if ($rule->valid_from && $checkOut->lt(Carbon::parse($rule->valid_from))) continue;
    //         if ($rule->valid_until && $checkIn->gt(Carbon::parse($rule->valid_until))) continue;

    //         switch ($rule->pattern_type) {

    //             case 'date_range':
    //                 $rangeStart = Carbon::parse($rule->start_date);
    //                 $rangeEnd = Carbon::parse($rule->end_date);

    //                 // If booking overlaps the rule range at all
    //                 if ($checkIn->lte($rangeEnd) && $checkOut->gte($rangeStart)) {
    //                     $available = $rule->rule_mode === 'active';
    //                 }
    //                 break;

    //             case 'weekly':
    //                 // Loop through all days in booking period
    //                 $period = new CarbonPeriod($checkIn, $checkOut);
    //                 foreach ($period as $day) {
    //                     if ($day->dayOfWeek === $rule->day_of_week) {
    //                         $available = $rule->rule_mode === 'active';
    //                     }
    //                 }
    //                 break;

    //             case 'monthly':
    //                 $period = new CarbonPeriod($checkIn, $checkOut);
    //                 foreach ($period as $day) {
    //                     if ($day->day === $rule->day_of_month) {
    //                         $available = $rule->rule_mode === 'active';
    //                     }
    //                 }
    //                 break;

    //             case 'yearly':
    //                 $period = new CarbonPeriod($checkIn, $checkOut);
    //                 foreach ($period as $day) {
    //                     if ($day->day === $rule->day_of_month && $day->month === $rule->month_of_year) {
    //                         $available = $rule->rule_mode === 'active';
    //                     }
    //                 }
    //                 break;
    //         }
    //     }

    //     return $available;
    // }
}
