<?php

namespace App\Models;

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

class TimeSlot extends Model
{
    use HasFactory;

    protected $fillable = [
        'equipment_id',
        'slot_date',
        'start_time',
        'end_time',
        'status',
        'reservation_id',
        'notes'
    ];

    protected $casts = [
        'slot_date' => 'date',
        'start_time' => 'datetime:H:i',
        'end_time' => 'datetime:H:i',
    ];

    /**
     * Get all available statuses.
     */
    public static function getStatuses(): array
    {
        return [
            'available' => 'Available',
            'reserved' => 'Reserved',
            'blocked' => 'Blocked',
            'maintenance' => 'Maintenance'
        ];
    }

    /**
     * Get the formatted status name.
     */
    public function getStatusNameAttribute(): string
    {
        return self::getStatuses()[$this->status] ?? ucfirst($this->status);
    }

    /**
     * Get the status badge class for UI.
     */
    public function getStatusBadgeClassAttribute(): string
    {
        return match($this->status) {
            'available' => 'bg-success',
            'reserved' => 'bg-primary',
            'blocked' => 'bg-warning',
            'maintenance' => 'bg-danger',
            default => 'bg-secondary'
        };
    }

    /**
     * Check if the time slot is available.
     */
    public function isAvailable(): bool
    {
        return $this->status === 'available';
    }

    /**
     * Check if the time slot is reserved.
     */
    public function isReserved(): bool
    {
        return $this->status === 'reserved';
    }

    /**
     * Check if the time slot is in the past.
     */
    public function isPast(): bool
    {
        $slotDateTime = $this->slot_date->copy()->setTimeFrom($this->start_time);
        return $slotDateTime->isPast();
    }

    /**
     * Check if the time slot is today.
     */
    public function isToday(): bool
    {
        return $this->slot_date->isToday();
    }

    /**
     * Check if the time slot is in the future.
     */
    public function isFuture(): bool
    {
        $slotDateTime = $this->slot_date->copy()->setTimeFrom($this->start_time);
        return $slotDateTime->isFuture();
    }

    /**
     * Check if the time slot is currently active.
     * A time slot is considered current if it's today and the current time
     * is within 30 minutes before or after the slot's time range.
     */
    public function isCurrent(): bool
    {
        if (!$this->isToday()) {
            return false;
        }
        
        $now = now();
        $slotStart = $this->slot_date->copy()->setTimeFrom($this->start_time);
        $slotEnd = $this->slot_date->copy()->setTimeFrom($this->end_time);
        
        // Check if current time is within 30 minutes before start or after end
        $thirtyMinutesBeforeStart = $slotStart->copy()->subMinutes(30);
        $thirtyMinutesAfterEnd = $slotEnd->copy()->addMinutes(30);
        
        return $now->between($thirtyMinutesBeforeStart, $thirtyMinutesAfterEnd);
    }

    /**
     * Get the duration in minutes.
     */
    public function getDurationMinutesAttribute(): int
    {
        return $this->start_time->diffInMinutes($this->end_time);
    }

    /**
     * Get the formatted duration.
     */
    public function getFormattedDurationAttribute(): string
    {
        $minutes = $this->duration_minutes;
        if ($minutes < 60) {
            return "{$minutes} minutes";
        }
        
        $hours = floor($minutes / 60);
        $remainingMinutes = $minutes % 60;
        
        if ($remainingMinutes === 0) {
            return "{$hours} hour" . ($hours > 1 ? 's' : '');
        }
        
        return "{$hours}h {$remainingMinutes}m";
    }

    /**
     * Scope a query to only include available time slots.
     */
    public function scopeAvailable($query)
    {
        return $query->where('status', 'available');
    }

    /**
     * Scope a query to only include reserved time slots.
     */
    public function scopeReserved($query)
    {
        return $query->where('status', 'reserved');
    }

    /**
     * Scope a query to only include time slots for a specific equipment.
     */
    public function scopeForEquipment($query, $equipmentId)
    {
        return $query->where('equipment_id', $equipmentId);
    }

    /**
     * Scope a query to only include time slots for a specific date.
     */
    public function scopeForDate($query, $date)
    {
        return $query->where('slot_date', $date);
    }

    /**
     * Scope a query to only include time slots for a date range.
     */
    public function scopeForDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('slot_date', [$startDate, $endDate]);
    }

    /**
     * Scope a query to only include future time slots.
     */
    public function scopeFuture($query)
    {
        $now = now();
        $today = $now->toDateString();
        $currentTime = $now->format('H:i:s');
        
        return $query->where(function ($q) use ($today, $currentTime) {
            // Date is in the future
            $q->where('slot_date', '>', $today)
              // OR date is today but time is in the future
              ->orWhere(function ($subQ) use ($today, $currentTime) {
                  $subQ->where('slot_date', $today)
                       ->where('start_time', '>', $currentTime);
              });
        });
    }

    /**
     * Scope a query to only include past time slots.
     */
    public function scopePast($query)
    {
        $now = now();
        $today = $now->toDateString();
        $currentTime = $now->format('H:i:s');
        
        return $query->where(function ($q) use ($today, $currentTime) {
            // Date is in the past
            $q->where('slot_date', '<', $today)
              // OR date is today but time has passed
              ->orWhere(function ($subQ) use ($today, $currentTime) {
                  $subQ->where('slot_date', $today)
                       ->where('start_time', '<', $currentTime);
              });
        });
    }

    /**
     * Scope a query to only include today's time slots.
     */
    public function scopeToday($query)
    {
        return $query->where('slot_date', now()->toDateString());
    }

    /**
     * Scope a query to only include current/active time slots.
     * A time slot is considered current if it's today and the current time
     * is within 30 minutes before or after the slot's time range.
     */
    public function scopeCurrent($query)
    {
        $now = now();
        $today = $now->toDateString();
        $currentTime = $now->format('H:i:s');
        $thirtyMinutesAgo = $now->copy()->subMinutes(30)->format('H:i:s');
        $thirtyMinutesFromNow = $now->copy()->addMinutes(30)->format('H:i:s');
        
        return $query->where('slot_date', $today)
                    ->where('start_time', '<=', $thirtyMinutesFromNow)
                    ->where('end_time', '>=', $thirtyMinutesAgo);
    }

    /**
     * Get the relationships.
     */
    public function equipment()
    {
        return $this->belongsTo(Equipment::class);
    }

    public function reservation()
    {
        return $this->belongsTo(EquipmentReservation::class);
    }

    /**
     * Get a summary of the time slot for API responses.
     */
    public function toApiArray(): array
    {
        return [
            'id' => $this->id,
            'equipment_id' => $this->equipment_id,
            'equipment_name' => $this->equipment->name ?? '',
            'slot_date' => $this->slot_date->format('Y-m-d'),
            'formatted_date' => $this->slot_date->format('M d, Y'),
            'start_time' => $this->start_time->format('H:i'),
            'end_time' => $this->end_time->format('H:i'),
            'formatted_time_range' => $this->start_time->format('H:i') . ' - ' . $this->end_time->format('H:i'),
            'status' => $this->status,
            'status_name' => $this->status_name,
            'status_badge_class' => $this->status_badge_class,
            'duration_minutes' => $this->duration_minutes,
            'formatted_duration' => $this->formatted_duration,
            'is_past' => $this->isPast(),
            'is_today' => $this->isToday(),
            'is_future' => $this->isFuture(),
            'is_current' => $this->isCurrent(),
            'is_available' => $this->isAvailable(),
            'is_reserved' => $this->isReserved(),
            'reservation_id' => $this->reservation_id,
            'notes' => $this->notes,
            'created_at' => $this->created_at->toISOString(),
            'updated_at' => $this->updated_at->toISOString(),
        ];
    }
}
