'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import Swal from 'sweetalert2';
import { RequireRole, useAuth } from '@/lib/auth-context';
import {
  EmptyState,
  ErrorAlert,
  Loading,
  PageHeader,
  formatCpf,
} from '@/components/app/ui';
import AppointmentModal from '@/components/app/agenda/AppointmentModal';
import { extractApiError } from '@/lib/api-client';
import {
  addDays,
  formatLongDate,
  formatTimeInZone,
  todayInZone,
  zonedToUtcIso,
} from '@/lib/datetime';
import {
  cancelAppointment,
  createScheduleBlock,
  getClinicSettings,
  listAppointments,
  listScheduleBlocks,
  removeScheduleBlock,
  updateAppointment,
} from '@/lib/services/appointments';
import { getMyDentist, listDentists } from '@/lib/services/dentists';
import {
  ACTIVE_APPOINTMENT_STATUSES,
  APPOINTMENT_SOURCE_LABELS,
  APPOINTMENT_STATUS_BADGES,
  APPOINTMENT_STATUS_LABELS,
  type Appointment,
  type AppointmentStatus,
  type Dentist,
  type ScheduleBlock,
} from '@/lib/types';

const FALLBACK_TIMEZONE = 'America/Sao_Paulo';

export default function AgendaPage() {
  return (
    <RequireRole roles={['admin', 'receptionist', 'dentist']}>
      <AgendaContent />
    </RequireRole>
  );
}

function AgendaContent() {
  const { user } = useAuth();
  const isDentist = user?.role === 'dentist';
  /** Perfil do dentista logado: só pode alterar as próprias consultas. */
  const [ownDentistId, setOwnDentistId] = useState<number | null>(null);
  const [timezone, setTimezone] = useState(FALLBACK_TIMEZONE);
  const [date, setDate] = useState<string>(() => todayInZone(FALLBACK_TIMEZONE));
  const [dentistFilter, setDentistFilter] = useState<number | ''>('');
  const [dentists, setDentists] = useState<Dentist[]>([]);

  const [appointments, setAppointments] = useState<Appointment[]>([]);
  const [blocks, setBlocks] = useState<ScheduleBlock[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [modalOpen, setModalOpen] = useState(false);
  const [modalMode, setModalMode] = useState<'create' | 'reschedule'>('create');
  const [modalAppointment, setModalAppointment] =
    useState<Appointment | null>(null);

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

  // Descobre o fuso da clínica e ajusta a data inicial.
  useEffect(() => {
    let active = true;
    (async () => {
      try {
        const settings = await getClinicSettings();
        const tz =
          typeof settings.timezone === 'string'
            ? settings.timezone
            : FALLBACK_TIMEZONE;
        if (!active) return;
        setTimezone(tz);
        setDate(todayInZone(tz));
      } catch {
        /* mantém o padrão */
      }
    })();
    return () => {
      active = false;
    };
  }, []);

  useEffect(() => {
    let active = true;
    (async () => {
      try {
        const page = await listDentists({ limit: 100 });
        if (active) setDentists(page.data);
      } catch {
        /* silencioso */
      }
    })();
    return () => {
      active = false;
    };
  }, []);

  useEffect(() => {
    if (!isDentist) return;
    getMyDentist()
      .then((d) => setOwnDentistId(Number(d.id)))
      .catch(() => setOwnDentistId(null));
  }, [isDentist]);

  function canManage(appointment: Appointment): boolean {
    return !isDentist || Number(appointment.dentistId) === ownDentistId;
  }

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const dentistId = dentistFilter === '' ? undefined : Number(dentistFilter);
      const [appointmentPage, blockList] = await Promise.all([
        listAppointments({ date, dentistId, limit: 100 }),
        listScheduleBlocks({ date, dentistId }),
      ]);
      setAppointments(appointmentPage.data);
      setBlocks(blockList);
    } catch (err) {
      setError(extractApiError(err));
    } finally {
      setLoading(false);
    }
  }, [date, dentistFilter]);

  useEffect(() => {
    load();
  }, [load]);

  function openCreate() {
    setModalMode('create');
    setModalAppointment(null);
    setModalOpen(true);
  }

  function openReschedule(appointment: Appointment) {
    setModalMode('reschedule');
    setModalAppointment(appointment);
    setModalOpen(true);
  }

  async function handleStatus(
    appointment: Appointment,
    status: AppointmentStatus,
  ) {
    try {
      await updateAppointment(appointment.id, { status });
      load();
    } catch (err) {
      Swal.fire({ icon: 'error', title: 'Erro', text: extractApiError(err) });
    }
  }

  async function handleCancel(appointment: Appointment) {
    const { value, isConfirmed } = await Swal.fire<string>({
      icon: 'warning',
      title: 'Cancelar agendamento?',
      input: 'text',
      inputLabel: 'Motivo (opcional)',
      inputPlaceholder: 'Ex.: paciente solicitou',
      showCancelButton: true,
      confirmButtonText: 'Cancelar agendamento',
      cancelButtonText: 'Voltar',
      confirmButtonColor: '#dc3545',
    });
    if (!isConfirmed) return;
    try {
      await cancelAppointment(appointment.id, value || undefined);
      load();
    } catch (err) {
      Swal.fire({ icon: 'error', title: 'Erro', text: extractApiError(err) });
    }
  }

  async function handleCreateBlock() {
    const dentistOptions = activeDentists
      .map((d) => `<option value="${d.id}">${d.fullName}</option>`)
      .join('');

    const { value } = await Swal.fire({
      title: 'Bloquear agenda',
      html: `
        <div class="text-start">
          <label class="form-label">Dentista</label>
          <select id="bk-dentist" class="form-select mb-2">${dentistOptions}</select>
          <label class="form-label">Data</label>
          <input id="bk-date" type="date" class="form-control mb-2" value="${date}">
          <div class="row g-2">
            <div class="col-6">
              <label class="form-label">Início</label>
              <input id="bk-start" type="time" class="form-control" value="08:00">
            </div>
            <div class="col-6">
              <label class="form-label">Fim</label>
              <input id="bk-end" type="time" class="form-control" value="12:00">
            </div>
          </div>
          <label class="form-label mt-2">Motivo</label>
          <input id="bk-reason" type="text" class="form-control" maxlength="255" placeholder="Ex.: férias, almoço, congresso">
        </div>`,
      focusConfirm: false,
      showCancelButton: true,
      confirmButtonText: 'Bloquear',
      cancelButtonText: 'Cancelar',
      preConfirm: () => {
        const get = (id: string) =>
          (document.getElementById(id) as HTMLInputElement | HTMLSelectElement)
            .value;
        const dentistId = Number(get('bk-dentist'));
        const blockDate = get('bk-date');
        const startTime = get('bk-start');
        const endTime = get('bk-end');
        const reason = get('bk-reason');
        if (!dentistId || !blockDate || !startTime || !endTime) {
          Swal.showValidationMessage('Preencha dentista, data e horários');
          return false;
        }
        if (startTime >= endTime) {
          Swal.showValidationMessage('O início deve ser anterior ao fim');
          return false;
        }
        return {
          dentistId,
          startAt: zonedToUtcIso(blockDate, startTime, timezone),
          endAt: zonedToUtcIso(blockDate, endTime, timezone),
          reason: reason || undefined,
        };
      },
    });

    if (!value) return;
    try {
      await createScheduleBlock(value);
      if (value.startAt.slice(0, 10) === date) load();
    } catch (err) {
      Swal.fire({ icon: 'error', title: 'Erro', text: extractApiError(err) });
    }
  }

  async function handleRemoveBlock(block: ScheduleBlock) {
    const confirm = await Swal.fire({
      icon: 'warning',
      title: 'Remover bloqueio?',
      showCancelButton: true,
      confirmButtonText: 'Remover',
      cancelButtonText: 'Cancelar',
      confirmButtonColor: '#dc3545',
    });
    if (!confirm.isConfirmed) return;
    try {
      await removeScheduleBlock(block.id);
      load();
    } catch (err) {
      Swal.fire({ icon: 'error', title: 'Erro', text: extractApiError(err) });
    }
  }

  const activeAppointments = appointments.filter((a) =>
    ACTIVE_APPOINTMENT_STATUSES.includes(a.status),
  );

  return (
    <>
      <PageHeader
        title="Agenda"
        subtitle={`Gestão de agendamentos · fuso ${timezone}`}
        action={
          <div className="d-flex gap-2">
            <button className="btn btn-outline-secondary" onClick={handleCreateBlock}>
              <i className="bi bi-calendar-x me-1" />
              Bloquear
            </button>
            <button className="btn btn-primary" onClick={openCreate}>
              <i className="bi bi-plus-lg me-1" />
              Novo agendamento
            </button>
          </div>
        }
      />

      <div className="card border-0 shadow-sm mb-3">
        <div className="card-body">
          <div className="row g-2 align-items-end">
            <div className="col-12 col-lg-auto">
              <div className="btn-group" role="group" aria-label="Navegação de dias">
                <button
                  className="btn btn-outline-secondary"
                  onClick={() => setDate((d) => addDays(d, -1))}
                  aria-label="Dia anterior"
                >
                  <i className="bi bi-chevron-left" />
                </button>
                <button
                  className="btn btn-outline-secondary"
                  onClick={() => setDate(todayInZone(timezone))}
                >
                  Hoje
                </button>
                <button
                  className="btn btn-outline-secondary"
                  onClick={() => setDate((d) => addDays(d, 1))}
                  aria-label="Próximo dia"
                >
                  <i className="bi bi-chevron-right" />
                </button>
              </div>
            </div>
            <div className="col-12 col-sm-6 col-lg-3">
              <label className="form-label small mb-1" htmlFor="agenda-date">
                Data
              </label>
              <input
                id="agenda-date"
                type="date"
                className="form-control"
                value={date}
                onChange={(e) => setDate(e.target.value)}
              />
            </div>
            <div className="col-12 col-sm-6 col-lg-4">
              <label className="form-label small mb-1" htmlFor="agenda-dentist">
                Dentista
              </label>
              <select
                id="agenda-dentist"
                className="form-select"
                value={dentistFilter}
                onChange={(e) =>
                  setDentistFilter(e.target.value ? Number(e.target.value) : '')
                }
              >
                <option value="">Todos os dentistas</option>
                {activeDentists.map((d) => (
                  <option key={d.id} value={d.id}>
                    {d.fullName}
                  </option>
                ))}
              </select>
            </div>
          </div>
          <p className="text-muted small mb-0 mt-3">
            <i className="bi bi-calendar3 me-1" />
            {formatLongDate(date)} · {activeAppointments.length} agendamento(s)
            ativo(s)
            {blocks.length > 0 && ` · ${blocks.length} bloqueio(s)`}
          </p>
        </div>
      </div>

      {error ? (
        <ErrorAlert message={error} onRetry={load} />
      ) : loading ? (
        <Loading label="Carregando agenda…" />
      ) : (
        <>
          <div className="card border-0 shadow-sm mb-3">
            <div className="card-header bg-white fw-semibold">
              <i className="bi bi-calendar-check me-2 text-primary" />
              Agendamentos
            </div>
            {appointments.length === 0 ? (
              <EmptyState
                icon="bi-calendar3"
                title="Nenhum agendamento neste dia"
                description="Crie um novo agendamento para começar."
              />
            ) : (
              <div className="table-responsive">
                <table className="table align-middle mb-0 table-nowrap">
                  <thead className="table-light">
                    <tr>
                      <th>Horário</th>
                      <th>Paciente</th>
                      <th>Dentista</th>
                      <th>Motivo</th>
                      <th>Origem</th>
                      <th>Status</th>
                      <th className="text-end">Ações</th>
                    </tr>
                  </thead>
                  <tbody>
                    {appointments.map((appointment) => {
                      const isActive =
                        ACTIVE_APPOINTMENT_STATUSES.includes(
                          appointment.status,
                        ) && canManage(appointment);
                      // A API só aceita concluído/falta após o início
                      const hasStarted =
                        new Date(appointment.startAt).getTime() <= Date.now();
                      return (
                        <tr key={appointment.id}>
                          <td className="fw-semibold">
                            {formatTimeInZone(appointment.startAt, timezone)}–
                            {formatTimeInZone(appointment.endAt, timezone)}
                          </td>
                          <td>
                            {appointment.patient?.fullName ?? '—'}
                            {appointment.patient?.cpf && (
                              <small className="text-muted d-block">
                                {formatCpf(appointment.patient.cpf)}
                              </small>
                            )}
                          </td>
                          <td>{appointment.dentist?.fullName ?? '—'}</td>
                          <td className="text-truncate" style={{ maxWidth: 200 }}>
                            {appointment.reason || '—'}
                          </td>
                          <td>
                            <span className="badge text-bg-light border">
                              {APPOINTMENT_SOURCE_LABELS[appointment.source]}
                            </span>
                          </td>
                          <td>
                            <span
                              className={`badge ${APPOINTMENT_STATUS_BADGES[appointment.status]}`}
                            >
                              {APPOINTMENT_STATUS_LABELS[appointment.status]}
                            </span>
                          </td>
                          <td className="text-end">
                            {isActive ? (
                              <div className="btn-group btn-group-sm">
                                {appointment.status === 'scheduled' && (
                                  <button
                                    className="btn btn-outline-primary"
                                    title="Confirmar"
                                    aria-label="Confirmar"
                                    onClick={() =>
                                      handleStatus(appointment, 'confirmed')
                                    }
                                  >
                                    <i className="bi bi-check2" />
                                  </button>
                                )}
                                <button
                                  className="btn btn-outline-secondary"
                                  title="Remarcar"
                                  aria-label="Remarcar"
                                  onClick={() => openReschedule(appointment)}
                                >
                                  <i className="bi bi-arrow-repeat" />
                                </button>
                                {hasStarted && (
                                  <>
                                    <button
                                      className="btn btn-outline-success"
                                      title="Concluir"
                                      aria-label="Concluir"
                                      onClick={() =>
                                        handleStatus(appointment, 'completed')
                                      }
                                    >
                                      <i className="bi bi-flag" />
                                    </button>
                                    <button
                                      className="btn btn-outline-warning"
                                      title="Não compareceu"
                                      aria-label="Não compareceu"
                                      onClick={() =>
                                        handleStatus(appointment, 'no_show')
                                      }
                                    >
                                      <i className="bi bi-person-x" />
                                    </button>
                                  </>
                                )}
                                <button
                                  className="btn btn-outline-danger"
                                  title="Cancelar"
                                  aria-label="Cancelar"
                                  onClick={() => handleCancel(appointment)}
                                >
                                  <i className="bi bi-x-lg" />
                                </button>
                              </div>
                            ) : (
                              <span className="text-muted small">—</span>
                            )}
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
          </div>

          <div className="card border-0 shadow-sm">
            <div className="card-header bg-white fw-semibold">
              <i className="bi bi-slash-circle me-2 text-secondary" />
              Bloqueios do dia
            </div>
            {blocks.length === 0 ? (
              <div className="card-body text-muted small">
                Sem bloqueios neste dia.
              </div>
            ) : (
              <div className="table-responsive">
                <table className="table align-middle mb-0 table-nowrap">
                  <thead className="table-light">
                    <tr>
                      <th>Horário</th>
                      <th>Dentista</th>
                      <th>Motivo</th>
                      <th className="text-end">Ações</th>
                    </tr>
                  </thead>
                  <tbody>
                    {blocks.map((block) => (
                      <tr key={block.id}>
                        <td className="fw-semibold">
                          {formatTimeInZone(block.startAt, timezone)}–
                          {formatTimeInZone(block.endAt, timezone)}
                        </td>
                        <td>{block.dentist?.fullName ?? `#${block.dentistId}`}</td>
                        <td>{block.reason || '—'}</td>
                        <td className="text-end">
                          <button
                            className="btn btn-sm btn-outline-danger"
                            onClick={() => handleRemoveBlock(block)}
                            aria-label="Remover bloqueio"
                          >
                            <i className="bi bi-trash" />
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        </>
      )}

      <AppointmentModal
        open={modalOpen}
        mode={modalMode}
        appointment={modalAppointment}
        timezone={timezone}
        defaultDate={date}
        onClose={() => setModalOpen(false)}
        onSaved={load}
      />
    </>
  );
}
