<?php

namespace App\Services;

use App\Models\Appointment;
use App\Models\Patient;
use App\Models\User;
use Carbon\Carbon;

class AppointmentService
{
    /**
     * Check for conflicting appointments for a therapist
     */
    public function hasConflict(int $therapistId, Carbon $startTime, int $duration, ?int $excludeId = null): bool
    {
        $endTime = $startTime->copy()->addMinutes($duration);

        $query = Appointment::where('user_id', $therapistId)
            ->whereIn('status', ['scheduled', 'confirmed', 'in_progress'])
            ->where(function ($q) use ($startTime, $endTime) {
                // Check if any appointment overlaps with the requested time
                $q->whereBetween('appointment_date', [$startTime, $endTime->copy()->subSecond()])
                  ->orWhereRaw("datetime(appointment_date, '+' || duration_minutes || ' minutes') BETWEEN ? AND ?", [$startTime, $endTime]);
            });

        if ($excludeId) {
            $query->where('id', '!=', $excludeId);
        }

        return $query->exists();
    }

    /**
     * Check for patient double-booking
     */
    public function hasPatientConflict(int $patientId, Carbon $startTime, int $duration, ?int $excludeId = null): bool
    {
        $endTime = $startTime->copy()->addMinutes($duration);

        $query = Appointment::where('patient_id', $patientId)
            ->whereIn('status', ['scheduled', 'confirmed', 'in_progress'])
            ->whereBetween('appointment_date', [$startTime, $endTime->copy()->subSecond()]);

        if ($excludeId) {
            $query->where('id', '!=', $excludeId);
        }

        return $query->exists();
    }

    /**
     * Get available time slots for a therapist on a given date
     */
    public function getAvailableSlots(int $therapistId, string $date, int $duration = 60): array
    {
        $workingHours = ['09:00', '17:00']; // 9 AM to 5 PM
        $slotInterval = 30; // minutes
        
        $slots = [];
        $start = Carbon::parse("$date {$workingHours[0]}");
        $end = Carbon::parse("$date {$workingHours[1]}");

        while ($start->lt($end)) {
            $slotEnd = $start->copy()->addMinutes($duration);
            
            if ($slotEnd->lte($end) && !$this->hasConflict($therapistId, $start, $duration)) {
                $slots[] = $start->format('H:i');
            }
            
            $start->addMinutes($slotInterval);
        }

        return $slots;
    }

    /**
     * Get calendar feed for a date range
     */
    public function getCalendarFeed(string $startDate, string $endDate, ?int $therapistId = null): array
    {
        $query = Appointment::with(['patient', 'user'])
            ->whereBetween('appointment_date', [$startDate, $endDate]);

        if ($therapistId) {
            $query->where('user_id', $therapistId);
        }

        return $query->orderBy('appointment_date')->get()->toArray();
    }

    /**
     * Consume a package session for an appointment
     */
    public function consumePackageSession(Appointment $appointment, int $patientPackageId): bool
    {
        $patientPackage = \App\Models\PatientPackage::find($patientPackageId);
        
        if (!$patientPackage || $patientPackage->patient_id !== $appointment->patient_id) {
            return false;
        }

        return $patientPackage->consumeSession();
    }
}
