<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreAppointmentRequest;
use App\Http\Requests\UpdateAppointmentRequest;
use App\Http\Resources\AppointmentResource;
use App\Models\Appointment;
use App\Services\AppointmentService;
use Illuminate\Http\Request;

class AppointmentController extends Controller
{
    protected $appointmentService;

    public function __construct(AppointmentService $appointmentService)
    {
        $this->appointmentService = $appointmentService;
    }

    public function index(Request $request)
    {
        $query = Appointment::with(['patient', 'user']);

        if ($request->has('patient_id')) {
            $query->where('patient_id', $request->patient_id);
        }

        if ($request->has('therapist_id')) {
            $query->where('user_id', $request->therapist_id);
        }

        if ($request->has('status')) {
            $query->where('status', $request->status);
        }

        if ($request->has('date_from')) {
            $query->whereDate('appointment_date', '>=', $request->date_from);
        }

        if ($request->has('date_to')) {
            $query->whereDate('appointment_date', '<=', $request->date_to);
        }

        if ($request->has('date')) {
            $query->whereDate('appointment_date', $request->date);
        }

        $appointments = $query->orderBy('appointment_date')->paginate($request->per_page ?? 20);

        return AppointmentResource::collection($appointments);
    }

    public function store(StoreAppointmentRequest $request)
    {
        $data = $request->validated();
        
        // Check for conflicts
        $appointmentDate = \Carbon\Carbon::parse($data['appointment_date']);
        
        if ($this->appointmentService->hasConflict($data['therapist_id'], $appointmentDate, $data['duration_minutes'])) {
            return response()->json([
                'message' => 'Therapist has a conflicting appointment at this time',
            ], 422);
        }

        if ($this->appointmentService->hasPatientConflict($data['patient_id'], $appointmentDate, $data['duration_minutes'])) {
            return response()->json([
                'message' => 'Patient has a conflicting appointment at this time',
            ], 422);
        }

        $appointment = Appointment::create([
            'patient_id' => $data['patient_id'],
            'user_id' => $data['therapist_id'],
            'appointment_date' => $data['appointment_date'],
            'duration_minutes' => $data['duration_minutes'],
            'notes' => $data['notes'] ?? null,
        ]);

        // Generate reminders
        $reminderService = new \App\Services\ReminderService();
        $reminderService->generateReminders($appointment);

        return new AppointmentResource($appointment);
    }

    public function show(Appointment $appointment)
    {
        return new AppointmentResource($appointment);
    }

    public function update(UpdateAppointmentRequest $request, Appointment $appointment)
    {
        $data = $request->validated();
        
        // Check for conflicts if date/therapist changed
        if (isset($data['appointment_date']) || isset($data['therapist_id'])) {
            $newDate = isset($data['appointment_date']) 
                ? \Carbon\Carbon::parse($data['appointment_date']) 
                : $appointment->appointment_date;
            $newTherapistId = $data['therapist_id'] ?? $appointment->user_id;
            $duration = $data['duration_minutes'] ?? $appointment->duration_minutes;
            
            if ($this->appointmentService->hasConflict($newTherapistId, $newDate, $duration, $appointment->id)) {
                return response()->json([
                    'message' => 'Therapist has a conflicting appointment at this time',
                ], 422);
            }
        }

        $appointment->update([
            'patient_id' => $data['patient_id'],
            'user_id' => $data['therapist_id'],
            'appointment_date' => $data['appointment_date'],
            'duration_minutes' => $data['duration_minutes'],
            'status' => $data['status'],
            'notes' => $data['notes'] ?? null,
            'cancellation_reason' => $data['cancellation_reason'] ?? null,
        ]);

        if ($data['status'] === 'cancelled') {
            $appointment->cancelled_by = auth()->id();
            $appointment->cancelled_at = now();
            $appointment->save();
        }

        return new AppointmentResource($appointment);
    }

    public function destroy(Appointment $appointment)
    {
        $appointment->delete();
        return response()->json(['message' => 'Appointment deleted successfully']);
    }

    public function calendar(Request $request)
    {
        $request->validate([
            'start' => 'required|date',
            'end' => 'required|date|after_or_equal:start',
        ]);

        $feed = $this->appointmentService->getCalendarFeed(
            $request->start,
            $request->end,
            $request->therapist_id
        );

        return response()->json($feed);
    }

    public function availableSlots(Request $request)
    {
        $request->validate([
            'therapist_id' => 'required|exists:users,id',
            'date' => 'required|date',
            'duration' => 'nullable|integer|min:15',
        ]);

        $slots = $this->appointmentService->getAvailableSlots(
            $request->therapist_id,
            $request->date,
            $request->duration ?? 60
        );

        return response()->json(['slots' => $slots]);
    }
}
