<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreAppointmentRequest;
use App\Http\Requests\UpdateAppointmentRequest;
use App\Models\Appointment;
use App\Models\Patient;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class AppointmentController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Appointment::class, 'appointment');
    }

    public function index(Request $request): View
    {
        $fecha = $request->date('fecha') ?? now()->startOfDay();

        $q = Appointment::query()
            ->with(['patient.client', 'assignedUser', 'author'])
            ->whereDate('starts_at', $fecha);

        if (! $request->boolean('incluir_canceladas')) {
            $q->where('status', '!=', Appointment::STATUS_CANCELLED);
        }

        $appointments = $q->orderBy('starts_at')->get();

        return view('clinica.appointments.index', compact('appointments', 'fecha'));
    }

    public function create(Request $request): View
    {
        $patients = Patient::query()->with('client')->orderBy('name')->get();
        $medicos = User::query()
            ->whereHas('roles', fn ($r) => $r->where('name', 'medico'))
            ->orderBy('name')
            ->get();
        $prefillPatientId = $request->integer('patient_id') ?: null;

        return view('clinica.appointments.create', compact('patients', 'medicos', 'prefillPatientId'));
    }

    public function store(StoreAppointmentRequest $request): RedirectResponse
    {
        $data = $request->validated();
        $patient = Patient::query()->findOrFail($data['patient_id']);

        Appointment::query()->create([
            'patient_id' => $patient->id,
            'client_id' => $patient->client_id,
            'assigned_to' => $data['assigned_to'] ?? null,
            'created_by' => $request->user()->id,
            'title' => $data['title'] ?? null,
            'starts_at' => $data['starts_at'],
            'ends_at' => $data['ends_at'],
            'status' => Appointment::STATUS_SCHEDULED,
            'notes' => $data['notes'] ?? null,
        ]);

        $fechaCita = \Illuminate\Support\Carbon::parse($data['starts_at'])->toDateString();

        return redirect()
            ->route('clinica.appointments.index', ['fecha' => $fechaCita])
            ->with('success', __('Cita registrada.'));
    }

    public function show(Appointment $appointment): View
    {
        $appointment->load(['patient.client', 'assignedUser', 'author']);

        return view('clinica.appointments.show', compact('appointment'));
    }

    public function edit(Appointment $appointment): View
    {
        $appointment->load(['patient.client']);
        $patients = Patient::query()->with('client')->orderBy('name')->get();
        $medicos = User::query()
            ->whereHas('roles', fn ($r) => $r->where('name', 'medico'))
            ->orderBy('name')
            ->get();

        return view('clinica.appointments.edit', compact('appointment', 'patients', 'medicos'));
    }

    public function update(UpdateAppointmentRequest $request, Appointment $appointment): RedirectResponse
    {
        $data = $request->validated();
        $patient = Patient::query()->findOrFail($data['patient_id']);

        $appointment->update([
            'patient_id' => $patient->id,
            'client_id' => $patient->client_id,
            'assigned_to' => $data['assigned_to'] ?? null,
            'title' => $data['title'] ?? null,
            'starts_at' => $data['starts_at'],
            'ends_at' => $data['ends_at'],
            'status' => $data['status'],
            'notes' => $data['notes'] ?? null,
        ]);

        return redirect()
            ->route('clinica.appointments.show', $appointment)
            ->with('success', __('Cita actualizada.'));
    }

    public function destroy(Appointment $appointment): RedirectResponse
    {
        $appointment->update(['status' => Appointment::STATUS_CANCELLED]);

        return redirect()
            ->route('clinica.appointments.index', ['fecha' => $appointment->starts_at->toDateString()])
            ->with('success', __('Cita cancelada.'));
    }
}
