'use client';

import { useEffect, useState } from 'react';
import {
  User,
  Activity,
  AlertTriangle,
  Building2,
  FileText,
  HeartPulse,
  Pill,
  Scissors,
  Syringe,
  TrendingUp,
  Users as UsersIcon,
  AlertCircle,
  ShieldCheck,
  File as FileIcon,
} from 'lucide-react';
import { GlassCard } from '@sehat/ui';
import { api, ApiClientError } from '@/lib/api-client';
import type {
  PatientEmrAllergy,
  PatientEmrCondition,
  PatientEmrFamilyHistory,
  PatientEmrHospitalisation,
  PatientEmrImmunization,
  PatientEmrLabResult,
  PatientEmrMedication,
  PatientEmrProcedure,
  PatientEmrRecord,
  PatientEmrReport,
  PatientLabFlag,
} from '@/lib/api-types';

const SEVERITY_STYLE: Record<PatientEmrAllergy['severity'], string> = {
  mild: 'bg-brand/12 text-brand',
  moderate: 'bg-accent/15 text-accent-dark',
  severe: 'bg-error/15 text-error',
};

interface Props {
  patientUserId: string;
  appointmentId?: string;
}

export function PatientEmrPanel({ patientUserId, appointmentId }: Props) {
  const [record, setRecord] = useState<PatientEmrRecord | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [errorCode, setErrorCode] = useState<number | null>(null);

  useEffect(() => {
    let cancelled = false;
    void (async () => {
      try {
        const r = await api.getPatientEmr(patientUserId, appointmentId);
        if (!cancelled) setRecord(r);
      } catch (e) {
        if (cancelled) return;
        if (e instanceof ApiClientError) {
          setError(e.message);
          setErrorCode(e.statusCode);
        } else {
          setError('Failed to load EMR');
        }
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [patientUserId, appointmentId]);

  if (error) {
    // 404 = patient hasn't started their EMR yet; show a softer message
    // than the 403 "no relationship" case.
    const isMissing = errorCode === 404;
    return (
      <GlassCard
        tone="light"
        padding="md"
        className={isMissing ? 'border-accent/40 bg-accent/5' : 'border-error/40 bg-error/10'}
      >
        <div
          className={`flex items-start gap-2 ${isMissing ? 'text-accent-dark' : 'text-error'}`}
        >
          {isMissing ? (
            <ShieldCheck className="mt-0.5 h-4 w-4 flex-shrink-0" />
          ) : (
            <AlertCircle className="mt-0.5 h-4 w-4 flex-shrink-0" />
          )}
          <p className="text-sm">
            {isMissing
              ? 'This patient has not built their EMR yet. Encourage them to complete the onboarding wizard before the consult.'
              : error}
          </p>
        </div>
      </GlassCard>
    );
  }

  if (!record) {
    return <p className="text-sm text-ink-muted">Loading patient record…</p>;
  }

  return (
    <div className="space-y-4">
      {record.demographics ? (
        <Section title="Demographics" icon={User}>
          <DemographicsBlock dems={record.demographics} />
        </Section>
      ) : null}

      {record.lifestyle ? (
        <Section title="Vitals & lifestyle" icon={Activity}>
          <LifestyleBlock lifestyle={record.lifestyle} />
        </Section>
      ) : null}

      {record.allergies.length > 0 ? (
        <Section title="Allergies" icon={AlertTriangle} highlight={hasSevereAllergy(record.allergies)}>
          <ul className="space-y-1.5">
            {record.allergies.map((a) => (
              <li key={a.id} className="flex items-center gap-2 text-sm text-ink">
                <span
                  className={`rounded-pill px-2 py-0.5 text-[10px] font-bold uppercase ${SEVERITY_STYLE[a.severity]}`}
                >
                  {a.severity}
                </span>
                <span className="font-semibold">{a.allergen}</span>
                {a.reaction ? <span className="text-ink-muted">— {a.reaction}</span> : null}
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.conditions.length > 0 ? (
        <Section title="Conditions" icon={HeartPulse}>
          <ul className="space-y-1.5 text-sm text-ink">
            {record.conditions.map((c) => (
              <li key={c.id} className="flex flex-wrap items-baseline gap-x-2">
                <span className="font-semibold">{c.conditionName}</span>
                {c.icdCode ? (
                  <span className="text-xs text-ink-subtle">({c.icdCode})</span>
                ) : null}
                <span className="rounded-pill bg-brand/10 px-2 py-0.5 text-[10px] font-bold uppercase text-brand">
                  {c.status}
                </span>
                {c.onsetDate ? (
                  <span className="text-xs text-ink-muted">
                    since {new Date(c.onsetDate).toLocaleDateString()}
                  </span>
                ) : null}
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.medications.length > 0 ? (
        <Section title="Current medications" icon={Pill}>
          <ul className="space-y-2">
            {record.medications.map((m) => (
              <li key={m.id} className="rounded-lg border border-surface-border bg-white p-2">
                <p className="text-sm font-bold text-ink">
                  {m.medicationName}
                  {m.genericName ? (
                    <span className="ml-1 text-xs font-normal italic text-ink-subtle">
                      ({m.genericName})
                    </span>
                  ) : null}
                </p>
                <p className="mt-0.5 text-xs text-ink-muted">
                  {m.dose} · {m.frequency} · {m.route}
                </p>
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.immunizations.length > 0 ? (
        <Section title="Immunizations" icon={Syringe}>
          <ul className="space-y-1 text-sm text-ink">
            {record.immunizations.map((i) => (
              <li key={i.id} className="flex flex-wrap items-baseline gap-x-2">
                <span className="font-semibold">{i.vaccineName}</span>
                {i.doseNumber ? (
                  <span className="text-xs text-ink-subtle">dose #{i.doseNumber}</span>
                ) : null}
                {i.administeredAt ? (
                  <span className="text-xs text-ink-muted">
                    {new Date(i.administeredAt).toLocaleDateString()}
                  </span>
                ) : null}
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.familyHistory.length > 0 ? (
        <Section title="Family history" icon={UsersIcon}>
          <ul className="space-y-1 text-sm text-ink">
            {record.familyHistory.map((f) => (
              <li key={f.id}>
                <span className="font-semibold">{f.relation.replace(/_/g, ' ')}</span>: {f.conditionName}
                {f.ageAtDiagnosis ? (
                  <span className="text-xs text-ink-muted"> (dx age {f.ageAtDiagnosis})</span>
                ) : null}
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.procedures && record.procedures.length > 0 ? (
        <Section title="Procedures & surgeries" icon={Scissors}>
          <ul className="space-y-1.5 text-sm text-ink">
            {record.procedures.map((p) => (
              <li key={p.id} className="flex flex-wrap items-baseline gap-x-2">
                <span className="font-semibold">{p.procedureName}</span>
                <span className="rounded-pill bg-brand/10 px-2 py-0.5 text-[10px] font-bold uppercase text-brand">
                  {p.procedureType}
                </span>
                {p.performedAt ? (
                  <span className="text-xs text-ink-muted">
                    {new Date(p.performedAt).toLocaleDateString()}
                  </span>
                ) : null}
                {p.hospital ? <span className="text-xs text-ink-subtle">{p.hospital}</span> : null}
                {p.outcome ? (
                  <p className="basis-full text-xs text-ink-muted">{p.outcome}</p>
                ) : null}
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.hospitalisations && record.hospitalisations.length > 0 ? (
        <Section title="Hospital stays" icon={Building2}>
          <ul className="space-y-2 text-sm text-ink">
            {record.hospitalisations.map((h) => (
              <li key={h.id} className="rounded-lg border border-surface-border bg-white p-2">
                <p className="font-bold">
                  {h.hospital}
                  <span className="ml-1.5 rounded-pill bg-error/12 px-2 py-0.5 text-[10px] font-bold uppercase text-error">
                    {h.admissionReason}
                  </span>
                </p>
                <p className="mt-0.5 text-xs text-ink">{h.reason}</p>
                <p className="text-xs text-ink-muted">
                  {new Date(h.admissionDate).toLocaleDateString()}
                  {h.dischargeDate ? ` → ${new Date(h.dischargeDate).toLocaleDateString()}` : ' → ongoing'}
                  {h.attendingDoctor ? ` · ${h.attendingDoctor}` : ''}
                </p>
                {h.dischargeSummary ? (
                  <p className="mt-1 line-clamp-3 text-xs text-ink-muted">{h.dischargeSummary}</p>
                ) : null}
              </li>
            ))}
          </ul>
        </Section>
      ) : null}

      {record.labResults && record.labResults.length > 0 ? (
        <Section title="Lab result trends" icon={TrendingUp}>
          <LabResultsBlock results={record.labResults} />
        </Section>
      ) : null}

      {record.reports && record.reports.length > 0 ? (
        <Section title="Medical reports" icon={FileText}>
          <ReportsBlock reports={record.reports} />
        </Section>
      ) : null}
    </div>
  );
}

const LAB_FLAG_STYLE: Record<PatientLabFlag, string> = {
  normal: 'bg-brand/12 text-brand',
  low: 'bg-accent/15 text-accent-dark',
  high: 'bg-accent/15 text-accent-dark',
  critical: 'bg-error/15 text-error',
};

function LabResultsBlock({ results }: { results: PatientEmrLabResult[] }) {
  // Group by test name and sort each series chronologically
  const byTest = new Map<string, PatientEmrLabResult[]>();
  for (const r of results) {
    const list = byTest.get(r.testName) ?? [];
    list.push(r);
    byTest.set(r.testName, list);
  }
  const series = Array.from(byTest.entries()).map(([name, list]) => ({
    name,
    points: [...list].sort(
      (a, b) => new Date(a.measuredAt).getTime() - new Date(b.measuredAt).getTime(),
    ),
  }));

  return (
    <div className="space-y-2">
      {series.map((s) => {
        const latest = s.points[s.points.length - 1]!;
        const first = s.points[0]!;
        const change = s.points.length >= 2 ? Number(latest.value) - Number(first.value) : 0;
        return (
          <div
            key={s.name}
            className="flex items-center justify-between rounded-lg border border-surface-border bg-white p-2"
          >
            <div className="min-w-0">
              <p className="text-sm font-bold text-ink">{s.name}</p>
              <p className="text-xs text-ink-muted">
                {s.points.length} reading{s.points.length === 1 ? '' : 's'}
                {latest.referenceRange ? ` · normal ${latest.referenceRange}` : ''}
              </p>
            </div>
            <div className="text-right">
              <p className="font-mono text-base font-bold text-ink">
                {latest.value} <span className="text-xs font-normal text-ink-muted">{latest.unit}</span>
              </p>
              <span
                className={`rounded-pill px-2 py-0.5 text-[10px] font-bold uppercase ${LAB_FLAG_STYLE[latest.flag]}`}
              >
                {latest.flag}
              </span>
              {s.points.length >= 2 ? (
                <p className="mt-0.5 text-[10px] text-ink-subtle">
                  Δ {change > 0 ? '+' : ''}
                  {change.toFixed(1)} since {new Date(first.measuredAt).toLocaleDateString()}
                </p>
              ) : null}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function ReportsBlock({ reports }: { reports: PatientEmrReport[] }) {
  return (
    <ul className="space-y-2">
      {reports.slice(0, 5).map((r) => (
        <li key={r.id} className="rounded-lg border border-surface-border bg-white p-2">
          <p className="text-sm font-bold text-ink">
            {r.title}
            <span className="ml-1.5 rounded-pill bg-brand/10 px-2 py-0.5 text-[10px] font-bold uppercase text-brand">
              {r.type.replace(/_/g, ' ')}
            </span>
          </p>
          <p className="text-xs text-ink-muted">
            {r.subType ? `${r.subType} · ` : ''}
            {r.reportDate ? new Date(r.reportDate).toLocaleDateString() : 'Date unknown'}
            {r.provider ? ` · ${r.provider}` : ''}
          </p>
          {r.files.length > 0 ? (
            <ul className="mt-1.5 flex flex-wrap gap-1.5">
              {r.files.map((f) => (
                <li
                  key={f.id}
                  className="inline-flex items-center gap-1 rounded border border-surface-border bg-white px-1.5 py-0.5 text-[10px] text-ink-muted"
                >
                  <FileIcon className="h-3 w-3 text-brand" />
                  <span className="max-w-[10rem] truncate">{f.name}</span>
                </li>
              ))}
            </ul>
          ) : null}
        </li>
      ))}
      {reports.length > 5 ? (
        <li className="text-xs text-ink-subtle">+ {reports.length - 5} more reports</li>
      ) : null}
    </ul>
  );
}

function Section({
  title,
  icon: Icon,
  highlight = false,
  children,
}: {
  title: string;
  icon: typeof User;
  highlight?: boolean;
  children: React.ReactNode;
}) {
  return (
    <GlassCard tone="light" padding="md" className={highlight ? 'border-error/40 bg-error/5' : ''}>
      <div className="mb-3 flex items-center gap-2 text-xs font-bold uppercase tracking-wide text-ink-muted">
        <Icon className={`h-4 w-4 ${highlight ? 'text-error' : 'text-brand'}`} />
        {title}
      </div>
      {children}
    </GlassCard>
  );
}

function DemographicsBlock({
  dems,
}: {
  dems: NonNullable<PatientEmrRecord['demographics']>;
}) {
  const age = computeAge(dems.dateOfBirth);
  return (
    <dl className="grid grid-cols-2 gap-x-4 gap-y-1 text-sm">
      <Field label="Name" value={`${dems.firstName} ${dems.lastName}`} />
      <Field label="Age / sex" value={`${age} · ${dems.gender}`} />
      {dems.bloodGroup ? <Field label="Blood group" value={dems.bloodGroup} /> : null}
      {dems.maritalStatus ? <Field label="Marital" value={dems.maritalStatus} /> : null}
      {dems.phone ? <Field label="Phone" value={dems.phone} /> : null}
      {dems.city ? (
        <Field label="Location" value={`${dems.city}${dems.country ? ', ' + dems.country : ''}`} />
      ) : null}
    </dl>
  );
}

function LifestyleBlock({
  lifestyle,
}: {
  lifestyle: NonNullable<PatientEmrRecord['lifestyle']>;
}) {
  const bp =
    lifestyle.bloodPressureSystolic && lifestyle.bloodPressureDiastolic
      ? `${lifestyle.bloodPressureSystolic} / ${lifestyle.bloodPressureDiastolic}`
      : null;
  const bmi =
    lifestyle.heightCm && lifestyle.weightKg
      ? computeBmi(parseFloat(lifestyle.heightCm), parseFloat(lifestyle.weightKg))
      : null;
  return (
    <dl className="grid grid-cols-2 gap-x-4 gap-y-1 text-sm">
      {lifestyle.heightCm ? <Field label="Height" value={`${lifestyle.heightCm} cm`} /> : null}
      {lifestyle.weightKg ? <Field label="Weight" value={`${lifestyle.weightKg} kg`} /> : null}
      {bmi ? <Field label="BMI" value={bmi.toFixed(1)} /> : null}
      {bp ? <Field label="Blood pressure" value={bp} /> : null}
      {lifestyle.smokingStatus ? (
        <Field label="Smoking" value={lifestyle.smokingStatus.replace(/_/g, ' ')} />
      ) : null}
      {lifestyle.alcoholFrequency ? <Field label="Alcohol" value={lifestyle.alcoholFrequency} /> : null}
      {lifestyle.exerciseFrequency ? (
        <Field label="Exercise" value={lifestyle.exerciseFrequency} />
      ) : null}
    </dl>
  );
}

function Field({ label, value }: { label: string; value: string }) {
  return (
    <>
      <dt className="text-xs uppercase tracking-wide text-ink-subtle">{label}</dt>
      <dd className="font-medium text-ink">{value}</dd>
    </>
  );
}

function computeAge(iso: string): string {
  const dob = new Date(iso);
  if (Number.isNaN(dob.getTime())) return '—';
  const now = new Date();
  let age = now.getFullYear() - dob.getFullYear();
  const m = now.getMonth() - dob.getMonth();
  if (m < 0 || (m === 0 && now.getDate() < dob.getDate())) age--;
  return `${age} yr`;
}

function computeBmi(heightCm: number, weightKg: number): number {
  const m = heightCm / 100;
  return weightKg / (m * m);
}

function hasSevereAllergy(allergies: PatientEmrAllergy[]): boolean {
  return allergies.some((a) => a.severity === 'severe');
}
