'use client';
import { useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { useSnackbar } from 'notistack';
import {
  Box,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Skeleton,
  Stack,
  Typography,
} from '@mui/material';
import { AppButton, EmptyState, ErrorState, PatientCard, PatientForm } from '@/components';
import { patientRecordPath } from '@/constants';
import { usePatients, useCreatePatient, useUpdatePatient, useArchivePatient } from '@/services/patients';
import { birthDateToAge } from '@/services/patients/age';
import type { CreatePatientInput, Patient } from '@/services/patients/types';

/**
 * E1 — the Patients tab: a cached, invalidate-on-mutation list of the customer's patients
 * with add/edit (the A4 form reused in a dialog) and soft archive (confirm). Loading skeleton
 * and an empty state with the add CTA are both handled.
 */
export default function PatientsPage() {
  const t = useTranslations('patients');
  const to = useTranslations('onboarding');
  const tc = useTranslations('common');
  const router = useRouter();
  const locale = useLocale();
  const { enqueueSnackbar } = useSnackbar();

  const { data, isLoading, isError, refetch } = usePatients();
  const createPatient = useCreatePatient();
  const updatePatient = useUpdatePatient();
  const archivePatient = useArchivePatient();

  const [formOpen, setFormOpen] = useState(false);
  const [editing, setEditing] = useState<Patient | null>(null);
  const [archiveTarget, setArchiveTarget] = useState<Patient | null>(null);

  const openAdd = () => {
    setEditing(null);
    setFormOpen(true);
  };
  const openEdit = (patient: Patient) => {
    setEditing(patient);
    setFormOpen(true);
  };
  const closeForm = () => setFormOpen(false);

  const handleSubmit = (input: CreatePatientInput) => {
    const onSuccess = () => {
      closeForm();
      enqueueSnackbar(to('saved'), { variant: 'success' });
    };
    if (editing) {
      updatePatient.mutate(
        { id: editing.id, input },
        { onSuccess, onError: () => enqueueSnackbar(t('unavailable'), { variant: 'error' }) },
      );
    } else {
      createPatient.mutate(input, { onSuccess });
    }
  };

  const confirmArchive = () => {
    if (!archiveTarget) return;
    const id = archiveTarget.id;
    setArchiveTarget(null);
    archivePatient.mutate(id, {
      onSuccess: () => enqueueSnackbar(t('archived'), { variant: 'success' }),
      // A cross-tenant/stale id returns 404 (not toasted by the fetch layer) — the archive was
      // optimistic, so tell the user why the card reappeared.
      onError: () => enqueueSnackbar(t('unavailable'), { variant: 'error' }),
    });
  };

  const patients = data?.items ?? [];
  const isEmpty = !isLoading && !isError && patients.length === 0;

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <Stack direction="row" sx={{ alignItems: 'flex-start', justifyContent: 'space-between', gap: 2 }}>
        <Box>
          <Typography variant="h5" component="h1">
            {t('title')}
          </Typography>
          <Typography variant="body2" sx={{ color: 'text.secondary' }}>
            {t('subtitle')}
          </Typography>
        </Box>
        {!isEmpty && !isError ? (
          <AppButton color="primary" variant="contained" startIcon="add" onClick={openAdd} sx={{ flexShrink: 0 }}>
            {t('add')}
          </AppButton>
        ) : null}
      </Stack>

      {isLoading ? (
        <Stack sx={{ gap: 1.5 }}>
          {[0, 1].map((key) => (
            <Skeleton key={key} variant="rounded" height={96} />
          ))}
        </Stack>
      ) : isError ? (
        <ErrorState message={t('load_error')} retryLabel={tc('retry')} onRetry={() => refetch()} />
      ) : isEmpty ? (
        <EmptyState
          icon="patients"
          title={t('empty_title')}
          body={t('empty_body')}
          action={
            <AppButton color="primary" variant="contained" startIcon="add" onClick={openAdd}>
              {t('add')}
            </AppButton>
          }
        />
      ) : (
        <Stack sx={{ gap: 1.5 }}>
          {patients.map((patient) => {
            const age = birthDateToAge(patient.birthDate);
            return (
              <PatientCard
                key={patient.id}
                patient={patient}
                relationLabel={patient.relation ? to(`relation_${patient.relation}`) : undefined}
                genderLabel={to(`gender_${patient.gender}`)}
                ageLabel={age == null ? undefined : t('age_years', { age })}
                conditionLabels={patient.conditions.map((code) => to(`condition_${code}`))}
                noConditionsLabel={t('conditions_none')}
                onOpen={() => router.push(`/${locale}${patientRecordPath(patient.id)}`)}
                openLabel={t('open_record', { name: patient.displayName })}
                onEdit={() => openEdit(patient)}
                onArchive={() => setArchiveTarget(patient)}
                editLabel={t('edit')}
                archiveLabel={t('archive')}
              />
            );
          })}
        </Stack>
      )}

      <Dialog open={formOpen} onClose={closeForm} fullWidth maxWidth="sm">
        <DialogTitle>{editing ? t('edit_title') : t('add_title')}</DialogTitle>
        <DialogContent>
          <Box sx={{ pt: 1 }}>
            <PatientForm
              key={editing?.id ?? 'new'}
              initial={
                editing
                  ? {
                      displayName: editing.displayName,
                      birthDate: editing.birthDate,
                      gender: editing.gender,
                      conditions: editing.conditions,
                      relation: editing.relation,
                    }
                  : undefined
              }
              showRelation
              submitLabel={tc('save')}
              submitting={createPatient.isPending || updatePatient.isPending}
              onSubmit={handleSubmit}
              onCancel={closeForm}
              cancelLabel={tc('cancel')}
            />
          </Box>
        </DialogContent>
      </Dialog>

      <Dialog open={Boolean(archiveTarget)} onClose={() => setArchiveTarget(null)}>
        <DialogTitle>{t('archive_title')}</DialogTitle>
        <DialogContent>
          <Typography variant="body2" sx={{ color: 'text.secondary' }}>
            {t('archive_body')}
          </Typography>
        </DialogContent>
        <DialogActions>
          <AppButton variant="text" onClick={() => setArchiveTarget(null)}>
            {tc('cancel')}
          </AppButton>
          <AppButton color="error" variant="contained" onClick={confirmArchive}>
            {t('archive_confirm')}
          </AppButton>
        </DialogActions>
      </Dialog>
    </Box>
  );
}
