<?php

namespace App\Models;

use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Addon extends Model
{
    use HasFactory;

    protected $fillable = [
        'sort_order',
        'title',
        'description',
        'price',
        'currency',
        'unit',

        'min_quantity',
        'max_quantity',
        'is_allow_select_quantity',
        'min_guests',
        'max_guests',
        'is_allow_select_guests',


        'calculation_type',
        'apply_on',
        'is_allow_select_days',
        'scope',

        'tag',
        'is_icon',
        'icon_value',
        'is_variant',
        'is_published',
        'default_active',
    ];

    protected $casts = [
        'is_allow_select_quantity' => 'boolean',
        'is_allow_select_guests' => 'boolean',
        'is_allow_select_days' => 'boolean',

        'is_icon' => 'boolean',

        'is_variant' => 'boolean',
        'default_active' => 'boolean',
        'is_published' => 'boolean',
    ];

    public function images()
    {
        return $this->morphMany(Imageable::class, 'imageable');
    }

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

    public function rooms()
    {
        return $this->belongsToMany(Room::class);
    }

    public function roomCategories()
    {
        return $this->belongsToMany(RoomCategory::class);
    }

    protected static function booted()
    {
        static::deleting(function ($addon) {
            $addon->availabilityRules()->delete();
        });
    }

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



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

        // Start with default_active
        $available = $this->default_active ?? 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;
    }
}
