'use client';

import Link from 'next/link';
import { useCallback, useEffect, useState } from 'react';
import { RequireRole, useAuth } from '@/lib/auth-context';
import { listPatients } from '@/lib/services/patients';
import { getMyDentist } from '@/lib/services/dentists';
import { getClinicSettings, listAppointments } from '@/lib/services/appointments';
import { listTreatmentPlans } from '@/lib/services/treatments';
import { FinanceReport, getFinanceReport } from '@/lib/services/finance';
import { countNewContactMessages } from '@/lib/services/contact-messages';
import { listExams } from '@/lib/services/exams';
import {
  APPOINTMENT_STATUS_BADGES,
  APPOINTMENT_STATUS_LABELS,
  type Appointment,
} from '@/lib/types';
import { PageHeader, Loading, ErrorAlert } from '@/components/app/ui';
import { extractApiError } from '@/lib/api-client';
import { formatTimeInZone, todayInZone } from '@/lib/datetime';
import { formatCents } from '@/lib/money';

const FALLBACK_TZ = 'America/Sao_Paulo';

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

interface DashboardData {
  timezone: string;
  today: Appointment[];
  patients: number;
  proposedPlans: number;
  examsPending: number;
  newMessages: number | null;
  finance: FinanceReport | null;
}

function monthBounds(today: string): { from: string; to: string } {
  const [year, month] = today.split('-').map(Number);
  const last = new Date(Date.UTC(year, month, 0)).getUTCDate();
  const mm = String(month).padStart(2, '0');
  return { from: `${year}-${mm}-01`, to: `${year}-${mm}-${String(last).padStart(2, '0')}` };
}

function Dashboard() {
  const { user } = useAuth();
  const role = user?.role;
  const isOffice = role === 'admin' || role === 'receptionist';
  const [data, setData] = useState<DashboardData | null>(null);
  const [error, setError] = useState<string | null>(null);

  const load = useCallback(async () => {
    setError(null);
    setData(null);
    try {
      const settings = await getClinicSettings().catch(() => null);
      const timezone =
        typeof settings?.timezone === 'string' ? settings.timezone : FALLBACK_TZ;
      const today = todayInZone(timezone);
      // Dentista vê a própria agenda; equipe vê a clínica inteira
      const dentistId =
        role === 'dentist' ? Number((await getMyDentist()).id) : undefined;
      const month = monthBounds(today);

      const [appointments, patients, plans, exams, messages, finance] = await Promise.all([
        listAppointments({ date: today, dentistId, limit: 100 }),
        listPatients({ limit: 1 }),
        listTreatmentPlans({ status: 'proposed', limit: 1 }),
        listExams({ status: 'requested', limit: 1 }),
        isOffice ? countNewContactMessages() : Promise.resolve(null),
        getFinanceReport(month.from, month.to).catch(() => null),
      ]);

      setData({
        timezone,
        today: appointments.data,
        patients: patients.total,
        proposedPlans: plans.total,
        examsPending: exams.total,
        newMessages: messages,
        finance,
      });
    } catch (err) {
      setError(extractApiError(err));
    }
  }, [role, isOffice]);

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

  if (error) return <ErrorAlert message={error} onRetry={load} />;
  if (!data) return <Loading label="Carregando indicadores…" />;

  const active = data.today.filter((a) => a.status !== 'cancelled');
  const upcoming = active.filter((a) => new Date(a.endAt).getTime() >= Date.now());

  const cards: { label: string; value: string; hint: string; icon: string; color: string; href: string }[] = [
    {
      label: role === 'dentist' ? 'Suas consultas hoje' : 'Consultas hoje',
      value: String(active.length),
      hint: `${upcoming.length} ainda por atender`,
      icon: 'bi-calendar3',
      color: 'primary',
      href: '/painel/agenda',
    },
    {
      label: 'Orçamentos aguardando',
      value: String(data.proposedPlans),
      hint: 'esperando aprovação do paciente',
      icon: 'bi-clipboard2-check',
      color: 'warning',
      href: '/painel/tratamentos',
    },
    {
      label: 'Exames sem marcação',
      value: String(data.examsPending),
      hint: 'pedidos aguardando data',
      icon: 'bi-file-earmark-medical',
      color: 'info',
      href: '/painel/exames',
    },
    {
      label: 'Pacientes',
      value: String(data.patients),
      hint: 'cadastrados',
      icon: 'bi-people',
      color: 'secondary',
      href: '/painel/pacientes',
    },
  ];

  if (data.finance) {
    cards.push(
      {
        label: role === 'dentist' ? 'Sua produção no mês' : 'Recebido no mês',
        value: formatCents(data.finance.netCents),
        hint: `${data.finance.paymentsCount} pagamento(s)`,
        icon: 'bi-cash-coin',
        color: 'success',
        href: '/painel/financeiro',
      },
      {
        label: 'Em atraso',
        value: formatCents(data.finance.overdueCents),
        hint: `${data.finance.overdueCount} cobrança(s) vencida(s)`,
        icon: 'bi-exclamation-triangle',
        color: 'danger',
        href: '/painel/financeiro',
      },
    );
  }
  if (data.newMessages !== null) {
    cards.push({
      label: 'Mensagens novas',
      value: String(data.newMessages),
      hint: 'do formulário de contato',
      icon: 'bi-envelope',
      color: 'primary',
      href: '/painel/mensagens',
    });
  }

  return (
    <>
      <PageHeader title={`Olá, ${user?.email ?? ''}`} subtitle="Visão geral da clínica" />

      <div className="row g-3 mb-4">
        {cards.map((card) => (
          <div className="col-12 col-sm-6 col-xl-3" key={card.label}>
            <Link href={card.href} className="text-decoration-none">
              <div className="card border-0 shadow-sm df-card-hover h-100">
                <div className="card-body d-flex align-items-center">
                  <div className={`bg-${card.color} bg-opacity-10 text-${card.color} rounded-3 p-3 me-3`}>
                    <i className={`bi ${card.icon} fs-4`} aria-hidden="true" />
                  </div>
                  <div className="min-w-0">
                    <div className="fs-4 fw-bold text-dark text-truncate">{card.value}</div>
                    <div className="text-dark small fw-semibold">{card.label}</div>
                    <div className="text-muted small">{card.hint}</div>
                  </div>
                </div>
              </div>
            </Link>
          </div>
        ))}
      </div>

      <div className="card border-0 shadow-sm">
        <div className="card-header bg-white d-flex justify-content-between align-items-center">
          <span className="fw-semibold">
            <i className="bi bi-clock me-2 text-primary" aria-hidden="true" />
            Agenda de hoje
          </span>
          <Link href="/painel/agenda" className="small">
            Abrir agenda
          </Link>
        </div>
        {active.length === 0 ? (
          <div className="card-body text-muted">Nenhuma consulta marcada para hoje.</div>
        ) : (
          <ul className="list-group list-group-flush">
            {active.map((a) => (
              <li key={a.id} className="list-group-item d-flex flex-wrap align-items-center gap-3">
                <span className="fw-semibold" style={{ minWidth: 100 }}>
                  {formatTimeInZone(a.startAt, data.timezone)}–{formatTimeInZone(a.endAt, data.timezone)}
                </span>
                <span className="flex-grow-1">
                  {a.patient?.fullName}
                  {role !== 'dentist' && <small className="text-muted"> · {a.dentist?.fullName}</small>}
                  {a.reason && <small className="d-block text-muted">{a.reason}</small>}
                </span>
                <span className={`badge ${APPOINTMENT_STATUS_BADGES[a.status]}`}>
                  {APPOINTMENT_STATUS_LABELS[a.status]}
                </span>
              </li>
            ))}
          </ul>
        )}
      </div>
    </>
  );
}
