<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;

final class Booking extends Model
{
    /** @use HasFactory<\Database\Factories\BookingFactory> */
    use HasFactory, LogsActivity;

    protected $fillable = [
        'property_id',
        'guest_id',
        'check_in_date',
        'check_out_date',
        'nights',
        'guests',
        'service_type',
        'price_per_night',
        'cleaning_fee',
        'service_fee',
        'setup_service_fee',
        'subtotal',
        'total_price',
        'status',
        'payment_status',
        'download_access_status',
        'download_access_url',
        'download_access_notes',
        'download_access_granted_by',
        'download_access_granted_at',
        'special_requests',
        'guest_phone',
        'cancellation_reason',
        'confirmed_at',
        'cancelled_at',
    ];

    protected function casts(): array
    {
        return [
            'property_id' => 'integer',
            'guest_id' => 'integer',
            'check_in_date' => 'date',
            'check_out_date' => 'date',
            'nights' => 'integer',
            'guests' => 'integer',
            'service_type' => 'string',
            'price_per_night' => 'decimal:2',
            'cleaning_fee' => 'decimal:2',
            'service_fee' => 'decimal:2',
            'setup_service_fee' => 'decimal:2',
            'subtotal' => 'decimal:2',
            'total_price' => 'decimal:2',
            'download_access_granted_by' => 'integer',
            'confirmed_at' => 'datetime',
            'cancelled_at' => 'datetime',
            'download_access_granted_at' => 'datetime',
            'created_at' => 'datetime',
            'updated_at' => 'datetime',
        ];
    }

    // Relationships

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

    public function guest(): BelongsTo
    {
        return $this->belongsTo(User::class, 'guest_id');
    }

    public function review(): HasOne
    {
        return $this->hasOne(Review::class);
    }

    public function transaction(): HasOne
    {
        return $this->hasOne(Transaction::class);
    }

    public function accessGrantedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'download_access_granted_by');
    }

    // Scopes

    public function scopePending($query)
    {
        return $query->whereIn('status', ['pending_verification', 'pending']);
    }

    public function scopeConfirmed($query)
    {
        return $query->where('status', 'confirmed');
    }

    public function scopeCancelled($query)
    {
        return $query->where('status', 'cancelled');
    }

    public function scopeCompleted($query)
    {
        return $query->where('status', 'completed');
    }

    public function scopeUpcoming($query)
    {
        return $query->where('check_in_date', '>', now())
            ->whereIn('status', ['pending_payment', 'pending', 'confirmed']);
    }

    public function scopeActive($query)
    {
        return $query->where('check_in_date', '<=', now())
            ->where('check_out_date', '>=', now())
            ->where('status', 'confirmed');
    }

    public function scopePast($query)
    {
        return $query->where('check_out_date', '<', now())
            ->whereIn('status', ['confirmed', 'completed']);
    }

    public function scopeForProperty($query, int $propertyId)
    {
        return $query->where('property_id', $propertyId);
    }

    public function scopeForGuest($query, int $guestId)
    {
        return $query->where('guest_id', $guestId);
    }

    // Helper Methods

    public function isPending(): bool
    {
        return $this->status === 'pending';
    }

    public function isConfirmed(): bool
    {
        return $this->status === 'confirmed';
    }

    public function isCancelled(): bool
    {
        return $this->status === 'cancelled';
    }

    public function isCompleted(): bool
    {
        return $this->status === 'completed';
    }

    public function canBeCancelled(): bool
    {
        return in_array($this->status, ['pending', 'confirmed'])
            && $this->check_in_date > now();
    }

    public function canBeConfirmed(): bool
    {
        return $this->status === 'pending';
    }

    public function canBeReviewed(): bool
    {
        return $this->status === 'completed'
            && $this->check_out_date < now()
            && ! $this->review()->exists();
    }

    public function hasReview(): bool
    {
        return $this->review()->exists();
    }

    public function hasDownloadAccess(): bool
    {
        return $this->download_access_status === 'granted'
            && ! empty($this->download_access_url);
    }

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly(['status', 'payment_status'])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }

    // Accessors for backward compatibility
    public function getCheckInAttribute()
    {
        return $this->check_in_date;
    }

    public function getCheckOutAttribute()
    {
        return $this->check_out_date;
    }

    public function getTotalAmountAttribute()
    {
        return $this->total_price;
    }
}
