<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    /** @use HasFactory<UserFactory> */
    use HasFactory, Notifiable, HasRoles;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'phone',
        'country',
        'address',
        'date_of_birth',
        'passport_number',
        'emergency_contact',
        'preferences',
        'is_admin',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'date_of_birth' => 'date',
            'preferences' => 'array',
        ];
    }

    public function bookings(): HasMany
    {
        return $this->hasMany(Booking::class);
    }

    public function confirmedBookings(): HasMany
    {
        return $this->hasMany(Booking::class)->where('status', 'confirmed');
    }

    public function pendingBookings(): HasMany
    {
        return $this->hasMany(Booking::class)->where('status', 'pending');
    }

    public function cancelledBookings(): HasMany
    {
        return $this->hasMany(Booking::class)->where('status', 'cancelled');
    }

    public function getFullNameAttribute(): string
    {
        return $this->name;
    }

    public function getIsAdminAttribute(): bool
    {
        return (bool) $this->attributes['is_admin'] ?? false;
    }

    public function getIsCustomerAttribute(): bool
    {
        return !$this->is_admin;
    }

    public function getTotalBookingsAttribute(): int
    {
        return $this->bookings()->count();
    }

    public function getTotalConfirmedBookingsAttribute(): int
    {
        return $this->confirmedBookings()->count();
    }

    public function getTotalSpentAttribute(): float
    {
        return $this->confirmedBookings()
            ->where('payment_status', 'paid')
            ->sum('total_price');
    }

    public function getFormattedTotalSpentAttribute(): string
    {
        return number_format($this->total_spent, 2) . ' USD';
    }

    public function upcomingBookings()
    {
        return $this->confirmedBookings()
            ->where('travel_date', '>=', now())
            ->orderBy('travel_date');
    }

    public function pastBookings()
    {
        return $this->confirmedBookings()
            ->where('travel_date', '<', now())
            ->orderBy('travel_date', 'desc');
    }

    public function hasActiveBooking(): bool
    {
        return $this->confirmedBookings()
            ->where('travel_date', '>=', now())
            ->exists();
    }

    public function canBookPackage(Package $package, int $people = 1): bool
    {
        if (!$package->is_available) {
            return false;
        }

        if ($people < $package->min_people || $people > $package->max_people) {
            return false;
        }

        if ($package->available_slots_count < $people) {
            return false;
        }

        return true;
    }
}
