<?php

namespace App\Models\DayTour;

use App\Models\Agency\Agency;
use App\Models\Definition\City;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

class DayTour extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'day_tours';

    protected $fillable = [
        'product_id',
        'agency_id',
        'code',
        'name',
        'slug',
        'description',
        'short_description',
        'places_to_visit',
        'inclusions',
        'exclusions',
        'cancellation_policy',
        'terms_conditions',
        'video_url',
        'documents',
        'tour_type',
        'has_guide',
        'languages',
        'has_transfer_points',
        'start_time',
        'end_time',
        'duration_hours',
        'recurring_days',
        'departure_city_id',
        'arrival_city_id',
        'destinations',
        'departure_latitude',
        'departure_longitude',
        'arrival_latitude',
        'arrival_longitude',
        'min_participants',
        'max_participants',
        'use_pricing_classes',
        'class_capacities',
        'min_age',
        'max_age',
        'child_friendly',
        'infant_allowed',
        'difficulty_level',
        'difficulty_description',
        'adult_price',
        'child_price',
        'infant_price',
        'child_min_age',
        'child_max_age',
        'infant_max_age',
        'currency',
        'payment_plan',
        'payment_plan_enabled',
        'online_payment_enabled',
        'online_deposit_percent',
        'auto_guarantee_on_min',
        'allows_custom_booking',
        'min_bookings_for_guaranteed',
        'auto_confirm_guaranteed',
        'instant_booking',
        'booking_deadline_hours',
        'cancellation_deadline_hours',
        'refundable',
        'meta_title',
        'meta_description',
        'meta_keywords',
        'tags',
        'is_featured',
        'is_bestseller',
        'is_new',
        'priority',
        'is_active',
        'is_public',
        'is_bookable',
        'is_draft',
        'published_at',
        'expires_at',
        'view_count',
        'booking_count',
        'wishlist_count',
        'rating_average',
        'rating_count',
        'external_ids',
        'api_data',
        'created_by',
        'updated_by',
    ];

    protected function casts(): array
    {
        return [
            'documents' => 'array',
            'languages' => 'array',
            'destinations' => 'array',
            'recurring_days' => 'array',
            'tags' => 'array',
            'external_ids' => 'array',
            'api_data' => 'array',
            'class_capacities' => 'array',
            'use_pricing_classes' => 'boolean',
            'has_guide' => 'boolean',
            'has_transfer_points' => 'boolean',
            'child_friendly' => 'boolean',
            'infant_allowed' => 'boolean',
            'allows_custom_booking' => 'boolean',
            'auto_confirm_guaranteed' => 'boolean',
            'instant_booking' => 'boolean',
            'refundable' => 'boolean',
            'is_featured' => 'boolean',
            'is_bestseller' => 'boolean',
            'is_new' => 'boolean',
            'is_active' => 'boolean',
            'is_public' => 'boolean',
            'is_bookable' => 'boolean',
            'is_draft' => 'boolean',
            'published_at' => 'datetime',
            'expires_at' => 'datetime',
            'adult_price' => 'decimal:2',
            'child_price' => 'decimal:2',
            'infant_price' => 'decimal:2',
            'payment_plan' => 'array',
            'payment_plan_enabled' => 'boolean',
            'online_payment_enabled' => 'boolean',
            'online_deposit_percent' => 'decimal:2',
            'auto_guarantee_on_min' => 'boolean',
            'departure_latitude' => 'decimal:8',
            'departure_longitude' => 'decimal:8',
            'arrival_latitude' => 'decimal:8',
            'arrival_longitude' => 'decimal:8',
            'rating_average' => 'decimal:2',
        ];
    }

    // Basic Relationships
    public function agency()
    {
        return $this->belongsTo(Agency::class);
    }

    public function product()
    {
        return $this->belongsTo(\App\Models\Product\Product::class, 'product_id');
    }

    public function departureCity()
    {
        return $this->belongsTo(City::class, 'departure_city_id');
    }

    public function arrivalCity()
    {
        return $this->belongsTo(City::class, 'arrival_city_id');
    }

    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function updater()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    // Categories relationship (through Product)
    // Pivot'un product_id'si products.id'ye FK'lı; parent key bu yüzden id DEĞİL product_id olmalı.
    public function categories()
    {
        return $this->belongsToMany(
            \App\Models\Product\ProductCategory::class,
            'product_category',
            'product_id',
            'category_id',
            'product_id', // parentKey
            'id'          // relatedKey
        );
    }

    // Tour Dates
    public function tourDates()
    {
        return $this->hasMany(DayTourDate::class)->orderBy('tour_date');
    }

    public function upcomingDates()
    {
        return $this->hasMany(DayTourDate::class)
            ->where('tour_date', '>=', now()->toDateString())
            ->where('is_active', true)
            ->orderBy('tour_date');
    }

    public function availableDates()
    {
        return $this->hasMany(DayTourDate::class)
            ->where('tour_date', '>=', now()->toDateString())
            ->where('is_active', true)
            ->whereIn('status', ['available', 'guaranteed'])
            ->orderBy('tour_date');
    }

    public function guaranteedDates()
    {
        return $this->hasMany(DayTourDate::class)
            ->where('is_guaranteed', true)
            ->where('is_active', true)
            ->orderBy('tour_date');
    }

    // Images
    public function images()
    {
        return $this->hasMany(DayTourImage::class)->ordered();
    }

    public function activeImages()
    {
        return $this->hasMany(DayTourImage::class)->active()->approved()->ordered();
    }

    public function coverImage()
    {
        return $this->hasOne(DayTourImage::class)->cover()->active();
    }

    public function featuredImages()
    {
        return $this->hasMany(DayTourImage::class)->featured()->active()->ordered();
    }

    public function galleryImages()
    {
        return $this->hasMany(DayTourImage::class)->forGallery()->active()->ordered();
    }

    // Itineraries
    public function itineraries()
    {
        return $this->hasMany(DayTourItinerary::class)->ordered();
    }

    public function activeItineraries()
    {
        return $this->hasMany(DayTourItinerary::class)->active()->ordered();
    }

    /**
     * Kademeli ödeme planı — tarih override'ı varsa onu, aksi halde tur planını verir.
     * (Şimdilik yalnızca konfigürasyon; tahsilat mantığı ileride bağlanacak.)
     */
    public function getEffectivePaymentPlan($date = null)
    {
        if ($date && $date->use_custom_payment_plan && !empty($date->payment_schedule)) {
            return $date->payment_schedule;
        }

        return $this->payment_plan_enabled ? ($this->payment_plan ?: []) : [];
    }

    /**
     * Benzersiz slug oluşturur. Aynı slug varsa sonuna -2, -3 gibi sayı ekler.
     * Soft-delete edilmiş kayıtlar da unique index'te yer tuttuğu için withTrashed ile aranır.
     */
    public static function generateUniqueSlug(string $name, ?int $excludeId = null): string
    {
        $originalSlug = Str::slug($name) ?: 'tur';
        $slug = $originalSlug;
        $counter = 2;

        while (static::withTrashed()
            ->where('slug', $slug)
            ->when($excludeId, fn ($q) => $q->where('id', '!=', $excludeId))
            ->exists()
        ) {
            $slug = $originalSlug . '-' . $counter++;
        }

        return $slug;
    }

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

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

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

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

    public function scopeNotDraft($query)
    {
        return $query->where('is_draft', false);
    }

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

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

    public function scopeByAgency($query, $agencyId)
    {
        return $query->where('agency_id', $agencyId);
    }

    public function scopeByTourType($query, $type)
    {
        return $query->where('tour_type', $type);
    }

    // Helper Methods
    public function isExpired()
    {
        return $this->expires_at && $this->expires_at->isPast();
    }

    public function isPublished()
    {
        return $this->published_at && $this->published_at->isPast();
    }

    public function isAvailable()
    {
        return $this->is_active && $this->is_public && $this->is_bookable && !$this->isExpired();
    }

    public function getRecurringDaysNames()
    {
        if (!$this->recurring_days || !is_array($this->recurring_days))
            return [];

        $dayNames = [
            'sunday' => 'Pazar',
            'monday' => 'Pazartesi',
            'tuesday' => 'Salı',
            'wednesday' => 'Çarşamba',
            'thursday' => 'Perşembe',
            'friday' => 'Cuma',
            'saturday' => 'Cumartesi'
        ];

        return collect($this->recurring_days)->map(fn($day) => $dayNames[$day] ?? $day)->toArray();
    }

    public function getCoverImageUrlAttribute()
    {
        return $this->coverImage?->image_url;
    }

    public function getThumbnailUrlAttribute()
    {
        return $this->coverImage?->thumbnail_url ?: $this->featuredImages->first()?->thumbnail_url;
    }

    public function hasImages()
    {
        return $this->activeImages()->count() > 0;
    }

    public function addImageFromDisk($diskItemId, array $attributes = [])
    {
        $defaultAttributes = [
            'disk_item_id' => $diskItemId,
            'image_type' => 'gallery',
            'sort_order' => $this->images()->count(),
            'is_active' => true,
            'is_approved' => true,
            'approved_at' => now(),
            'approved_by' => auth()->id(),
        ];

        return $this->images()->create(array_merge($defaultAttributes, $attributes));
    }

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($tour) {
            if (empty($tour->slug)) {
                $tour->slug = static::generateUniqueSlug((string) $tour->name);
            }

            if (empty($tour->code)) {
                $tour->code = 'DAY' . sprintf('%06d', static::count() + 1);
            }

            if (auth()->check()) {
                $tour->created_by = auth()->id();
            }
        });

        static::updating(function ($tour) {
            if (auth()->check()) {
                $tour->updated_by = auth()->id();
            }
        });
    }
}
