'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import Swal from 'sweetalert2';
import { Modal } from '@/components/app/ui';
import { extractApiError } from '@/lib/api-client';
import { formatDateInZone, dateStringInZone, todayInZone } from '@/lib/datetime';
import {
  createAppointment,
  getAvailability,
  rescheduleAppointment,
} from '@/lib/services/appointments';
import { listDentists } from '@/lib/services/dentists';
import { listPatients } from '@/lib/services/patients';
import { listSpecialties } from '@/lib/services/specialties';
import type {
  Appointment,
  AvailabilitySlot,
  Dentist,
  Patient,
  Specialty,
} from '@/lib/types';

type Mode = 'create' | 'reschedule';

export default function AppointmentModal({
  open,
  mode,
  appointment,
  timezone,
  defaultDate,
  onClose,
  onSaved,
}: {
  open: boolean;
  mode: Mode;
  appointment?: Appointment | null;
  timezone: string;
  defaultDate?: string;
  onClose: () => void;
  onSaved: () => void;
}) {
  const [dentists, setDentists] = useState<Dentist[]>([]);
  const [specialties, setSpecialties] = useState<Specialty[]>([]);
  const [patients, setPatients] = useState<Patient[]>([]);
  const [patientSearch, setPatientSearch] = useState('');
  const [patientLoading, setPatientLoading] = useState(false);

  const [patientId, setPatientId] = useState<number | ''>('');
  const [dentistId, setDentistId] = useState<number | ''>('');
  const [specialtyId, setSpecialtyId] = useState<number | ''>('');
  const [date, setDate] = useState<string>('');
  const [startAt, setStartAt] = useState<string>('');
  const [durationMinutes, setDurationMinutes] = useState<number>(30);
  const [reason, setReason] = useState('');

  const [slots, setSlots] = useState<AvailabilitySlot[]>([]);
  const [slotsLoading, setSlotsLoading] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const activeDentists = useMemo(
    () => dentists.filter((d) => d.isActive),
    [dentists],
  );

  // Inicializa o formulário sempre que o modal abre.
  useEffect(() => {
    if (!open) return;
    setError(null);
    setSubmitting(false);

    if (mode === 'reschedule' && appointment) {
      setPatientId(appointment.patientId);
      setDentistId(appointment.dentistId);
      setSpecialtyId(appointment.specialtyId ?? '');
      setDate(dateStringInZone(new Date(appointment.startAt), timezone));
      setDurationMinutes(
        Math.max(
          5,
          Math.round(
            (new Date(appointment.endAt).getTime() -
              new Date(appointment.startAt).getTime()) /
              60000,
          ),
        ),
      );
      setReason(appointment.reason ?? '');
      setStartAt(appointment.startAt);
    } else {
      setPatientId('');
      setDentistId('');
      setSpecialtyId('');
      setDate(defaultDate ?? todayInZone(timezone));
      setStartAt('');
      setDurationMinutes(30);
      setReason('');
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open, mode, appointment, timezone, defaultDate]);

  // Carrega dentistas e especialidades ao abrir.
  useEffect(() => {
    if (!open) return;
    let active = true;
    (async () => {
      try {
        const [dentistPage, specialtyPage] = await Promise.all([
          listDentists({ limit: 100 }),
          listSpecialties({ limit: 100 }),
        ]);
        if (!active) return;
        setDentists(dentistPage.data);
        setSpecialties(specialtyPage.data.filter((s) => s.isActive));
      } catch {
        /* silencioso: selects ficam vazios */
      }
    })();
    return () => {
      active = false;
    };
  }, [open]);

  // Busca de pacientes (somente no modo criação).
  const loadPatients = useCallback(async (search: string) => {
    setPatientLoading(true);
    try {
      const page = await listPatients({ limit: 100, search: search || undefined });
      setPatients(page.data);
    } catch {
      setPatients([]);
    } finally {
      setPatientLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!open || mode !== 'create') return;
    const timer = setTimeout(() => loadPatients(patientSearch.trim()), 300);
    return () => clearTimeout(timer);
  }, [open, mode, patientSearch, loadPatients]);

  // Carrega disponibilidade quando dentista e data estão definidos.
  useEffect(() => {
    if (!open || !dentistId || !date) {
      setSlots([]);
      return;
    }
    let active = true;
    setSlotsLoading(true);
    (async () => {
      try {
        const availability = await getAvailability(Number(dentistId), date);
        if (!active) return;
        setSlots(availability.slots);
      } catch {
        if (active) setSlots([]);
      } finally {
        if (active) setSlotsLoading(false);
      }
    })();
    return () => {
      active = false;
    };
  }, [open, dentistId, date]);

  async function handleSubmit(event: React.FormEvent) {
    event.preventDefault();
    setError(null);

    if (!dentistId || !date || !startAt) {
      setError('Selecione dentista, data e horário.');
      return;
    }
    if (mode === 'create' && !patientId) {
      setError('Selecione o paciente.');
      return;
    }

    setSubmitting(true);
    try {
      if (mode === 'reschedule' && appointment) {
        await rescheduleAppointment(appointment.id, {
          startAt,
          durationMinutes,
          reason: reason || undefined,
        });
      } else {
        await createAppointment({
          patientId: Number(patientId),
          dentistId: Number(dentistId),
          specialtyId: specialtyId ? Number(specialtyId) : undefined,
          startAt,
          durationMinutes,
          reason: reason || undefined,
        });
      }
      await Swal.fire({
        icon: 'success',
        title:
          mode === 'reschedule'
            ? 'Consulta remarcada'
            : 'Agendamento criado',
        timer: 1600,
        showConfirmButton: false,
      });
      onSaved();
      onClose();
    } catch (err) {
      setError(extractApiError(err));
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <Modal
      open={open}
      title={mode === 'reschedule' ? 'Remarcar consulta' : 'Novo agendamento'}
      onClose={onClose}
      busy={submitting}
      size="lg"
      footer={
        <>
          <button
            type="button"
            className="btn btn-outline-secondary"
            onClick={onClose}
            disabled={submitting}
          >
            Cancelar
          </button>
          <button
            type="submit"
            form="appointment-form"
            className="btn btn-primary"
            disabled={submitting}
          >
            {submitting ? (
              <span className="spinner-border spinner-border-sm me-2" />
            ) : (
              <i className="bi bi-check-lg me-1" />
            )}
            {mode === 'reschedule' ? 'Remarcar' : 'Agendar'}
          </button>
        </>
      }
    >
      <form id="appointment-form" onSubmit={handleSubmit} noValidate>
        {error && (
          <div className="alert alert-danger py-2" role="alert">
            {error}
          </div>
        )}

        {mode === 'reschedule' && appointment?.patient && (
          <div className="alert alert-light border py-2">
            <i className="bi bi-person me-1" />
            Paciente: <strong>{appointment.patient.fullName}</strong>
          </div>
        )}

        {mode === 'create' && (
          <div className="row g-3">
            <div className="col-md-6">
              <label className="form-label" htmlFor="ap-patient-search">
                Buscar paciente
              </label>
              <input
                id="ap-patient-search"
                type="search"
                className="form-control"
                placeholder="Nome, CPF ou e-mail"
                value={patientSearch}
                onChange={(e) => setPatientSearch(e.target.value)}
              />
            </div>
            <div className="col-md-6">
              <label className="form-label" htmlFor="ap-patient">
                Paciente *
              </label>
              <select
                id="ap-patient"
                className="form-select"
                value={patientId}
                onChange={(e) =>
                  setPatientId(e.target.value ? Number(e.target.value) : '')
                }
                required
              >
                <option value="">
                  {patientLoading ? 'Carregando…' : 'Selecione o paciente'}
                </option>
                {patients.map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.fullName}
                  </option>
                ))}
              </select>
            </div>
          </div>
        )}

        <div className="row g-3 mt-0">
          <div className="col-md-6">
            <label className="form-label" htmlFor="ap-dentist">
              Dentista *
            </label>
            <select
              id="ap-dentist"
              className="form-select"
              value={dentistId}
              onChange={(e) => {
                setDentistId(e.target.value ? Number(e.target.value) : '');
                setStartAt('');
              }}
              disabled={mode === 'reschedule'}
              required
            >
              <option value="">Selecione o dentista</option>
              {activeDentists.map((d) => (
                <option key={d.id} value={d.id}>
                  {d.fullName} — CRO {d.cro}/{d.croState}
                </option>
              ))}
            </select>
          </div>

          <div className="col-md-6">
            <label className="form-label" htmlFor="ap-specialty">
              Especialidade
            </label>
            <select
              id="ap-specialty"
              className="form-select"
              value={specialtyId}
              onChange={(e) =>
                setSpecialtyId(e.target.value ? Number(e.target.value) : '')
              }
            >
              <option value="">Não especificada</option>
              {specialties.map((s) => (
                <option key={s.id} value={s.id}>
                  {s.name}
                </option>
              ))}
            </select>
          </div>
        </div>

        <div className="row g-3 mt-0">
          <div className="col-md-6">
            <label className="form-label" htmlFor="ap-date">
              Data *
            </label>
            <input
              id="ap-date"
              type="date"
              className="form-control"
              value={date}
              min={mode === 'create' ? todayInZone(timezone) : undefined}
              onChange={(e) => {
                setDate(e.target.value);
                setStartAt('');
              }}
              required
            />
          </div>
          <div className="col-md-6">
            <label className="form-label" htmlFor="ap-slot">
              Horário *
            </label>
            <select
              id="ap-slot"
              className="form-select"
              value={startAt}
              onChange={(e) => setStartAt(e.target.value)}
              disabled={slotsLoading || !dentistId || !date}
              required
            >
              <option value="">
                {!dentistId
                  ? 'Escolha o dentista'
                  : slotsLoading
                    ? 'Carregando…'
                    : slots.length === 0
                      ? 'Sem horários neste dia'
                      : 'Selecione o horário'}
              </option>
              {slots.map((slot) => (
                <option
                  key={slot.startAt}
                  value={slot.startAt}
                  disabled={!slot.available}
                >
                  {slot.time}
                  {slot.available ? '' : ' (indisponível)'}
                </option>
              ))}
            </select>
          </div>
        </div>

        <div className="row g-3 mt-0">
          <div className="col-md-4">
            <label className="form-label" htmlFor="ap-duration">
              Duração (min)
            </label>
            <input
              id="ap-duration"
              type="number"
              className="form-control"
              min={5}
              max={480}
              step={5}
              value={durationMinutes}
              onChange={(e) => setDurationMinutes(Number(e.target.value))}
            />
          </div>
          <div className="col-md-8">
            <label className="form-label" htmlFor="ap-reason">
              Motivo
            </label>
            <input
              id="ap-reason"
              type="text"
              className="form-control"
              maxLength={255}
              value={reason}
              onChange={(e) => setReason(e.target.value)}
            />
          </div>
        </div>

        {startAt && (
          <p className="text-muted small mt-3 mb-0">
            <i className="bi bi-clock me-1" />
            {formatDateInZone(startAt, timezone)} às{' '}
            {new Intl.DateTimeFormat('pt-BR', {
              timeZone: timezone,
              hour: '2-digit',
              minute: '2-digit',
              hourCycle: 'h23',
            }).format(new Date(startAt))}{' '}
            ({timezone})
          </p>
        )}
      </form>
    </Modal>
  );
}
