"use client";

import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import {
  PageHeader,
  Button,
  Dialog,
  Input,
  DataTable,
  EmptyState,
  ErrorState,
} from "@/src/shared/ui";
import { healthcareApi } from "@/src/modules/healthcare/services/healthcare-api";
import { useHealthcarePatientContext } from "@/src/modules/healthcare/hooks/useHealthcarePatientContext";
import { useHealthcareLookups } from "@/src/modules/healthcare/hooks/useHealthcareLookups";
import {
  AppointmentsResourcePage,
  PrescriptionOrdersResourcePage,
  MedicalRecordsResourcePage,
  SettingsResourcePage,
  ExternalProvidersResourcePage,
  PatientsResourcePage,
} from "@/src/modules/healthcare/components/entities";
import {
  AggregateStatsRow,
  AnalyticsPage,
  HealthcarePageError,
  HealthcarePageLoader,
  ServiceMetaBadges,
} from "./shared";
import { AppointmentCard, PrescriptionCard, StatWidget } from "@/src/modules/healthcare/design-system";

function PatientGate({ children }: { children: (ctx: ReturnType<typeof useHealthcarePatientContext>) => React.ReactNode }) {
  const ctx = useHealthcarePatientContext();
  if (ctx.isLoading) return <HealthcarePageLoader label="در حال بارگذاری پروفایل بیمار…" />;
  if (ctx.error) return <HealthcarePageError error={ctx.error} onRetry={() => ctx.refetch()} />;
  if (!ctx.tenantId || !ctx.patientId) return <ErrorState message="پروفایل بیمار برای این workspace یافت نشد." />;
  return <>{children(ctx)}</>;
}

export function PatientDashboard() {
  return (
    <PatientGate>
      {(ctx) => <PatientDashboardInner tenantId={ctx.tenantId!} patientId={ctx.patientId!} patient={ctx.patient!} />}
    </PatientGate>
  );
}

function PatientDashboardInner({
  tenantId,
  patientId,
  patient,
}: {
  tenantId: string;
  patientId: string;
  patient: { display_name: string };
}) {
  const apptsQ = useQuery({
    queryKey: ["healthcare", tenantId, patientId, "portal-appointments"],
    queryFn: () => healthcareApi.patientPortal.appointments(tenantId, patientId),
  });
  const docsQ = useQuery({
    queryKey: ["healthcare", tenantId, patientId, "portal-docs"],
    queryFn: () => healthcareApi.patientPortal.documents(tenantId, patientId),
  });
  const { doctorName } = useHealthcareLookups();

  if (apptsQ.isLoading) return <HealthcarePageLoader />;
  if (apptsQ.error) return <HealthcarePageError error={apptsQ.error} onRetry={() => apptsQ.refetch()} />;

  const upcoming = (apptsQ.data?.items ?? []).filter((a) => new Date(a.scheduled_start) >= new Date());

  return (
    <div>
      <PageHeader title={`سلام ${patient.display_name}`} description="پرتal بیمار — داده واقعی." actions={<ServiceMetaBadges />} />
      <AggregateStatsRow
        stats={[
          { label: "نوبت پیش‌رو", value: upcoming.length },
          { label: "اسناد", value: docsQ.data?.length ?? 0 },
          { label: "کل نوبت‌ها", value: apptsQ.data?.total ?? 0 },
        ]}
      />
      <section className="mt-8 space-y-3">
        <h2 className="font-semibold text-secondary">نوبت‌های پیش‌رو</h2>
        {upcoming.length === 0 ? (
          <EmptyState title="نوبت پیش‌رویی نیست" />
        ) : (
          upcoming.map((a) => <AppointmentCard key={a.id} appointment={a} doctorName={doctorName(a.doctor_id)} />)
        )}
      </section>
    </div>
  );
}

export function PatientAppointmentsUpcoming() {
  return (
    <PatientGate>
      {(ctx) => (
        <PatientAppointmentsList tenantId={ctx.tenantId!} patientId={ctx.patientId!} upcoming />
      )}
    </PatientGate>
  );
}

export function PatientAppointmentsPast() {
  return (
    <PatientGate>
      {(ctx) => (
        <PatientAppointmentsList tenantId={ctx.tenantId!} patientId={ctx.patientId!} upcoming={false} />
      )}
    </PatientGate>
  );
}

function PatientAppointmentsList({
  tenantId,
  patientId,
  upcoming,
}: {
  tenantId: string;
  patientId: string;
  upcoming: boolean;
}) {
  const { doctorName } = useHealthcareLookups();
  const apptsQ = useQuery({
    queryKey: ["healthcare", tenantId, patientId, "appointments-list", upcoming],
    queryFn: () => healthcareApi.patientPortal.appointments(tenantId, patientId),
  });
  const qc = useQueryClient();
  const cancelM = useMutation({
    mutationFn: (a: { id: string; version: number }) =>
      healthcareApi.patientPortal.cancelAppointment(tenantId, patientId, a.id, { version: a.version }),
    onSuccess: async () => {
      toast.success("لغو شد");
      await qc.invalidateQueries({ queryKey: ["healthcare", tenantId, patientId] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (apptsQ.isLoading) return <HealthcarePageLoader />;
  if (apptsQ.error) return <HealthcarePageError error={apptsQ.error} onRetry={() => apptsQ.refetch()} />;

  const now = new Date();
  const items = (apptsQ.data?.items ?? []).filter((a) =>
    upcoming ? new Date(a.scheduled_start) >= now : new Date(a.scheduled_start) < now
  );

  return (
    <div>
      <PageHeader title={upcoming ? "نوبت‌های پیش‌رو" : "نوبت‌های گذشته"} />
      <div className="space-y-3">
        {items.map((a) => (
          <div key={a.id} className="flex flex-wrap items-center justify-between gap-2">
            <AppointmentCard appointment={a} doctorName={doctorName(a.doctor_id)} />
            {upcoming && a.status !== "cancelled" ? (
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() => cancelM.mutate({ id: a.id, version: a.version })}
                disabled={cancelM.isPending}
              >
                لغو
              </Button>
            ) : null}
          </div>
        ))}
      </div>
      {items.length === 0 ? <EmptyState title="نوبتی یافت نشد" /> : null}
    </div>
  );
}

export function PatientAppointmentsBook() {
  return (
    <PatientGate>
      {(ctx) => <PatientBookWizard tenantId={ctx.tenantId!} patientId={ctx.patientId!} />}
    </PatientGate>
  );
}

function PatientBookWizard({ tenantId, patientId }: { tenantId: string; patientId: string }) {
  const { clinics, doctors } = useHealthcareLookups();
  const [clinicId, setClinicId] = useState("");
  const [doctorId, setDoctorId] = useState("");
  const [start, setStart] = useState("");
  const [end, setEnd] = useState("");
  const qc = useQueryClient();

  const bookM = useMutation({
    mutationFn: () =>
      healthcareApi.patientPortal.bookAppointment(tenantId, patientId, {
        clinic_id: clinicId,
        doctor_id: doctorId,
        code: `PAT-${Date.now()}`,
        scheduled_start: new Date(start).toISOString(),
        scheduled_end: new Date(end).toISOString(),
      }),
    onSuccess: async () => {
      toast.success("نوبت ثبت شد");
      await qc.invalidateQueries({ queryKey: ["healthcare", tenantId, patientId] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  return (
    <div>
      <PageHeader title="رزرو نوبت" description="Wizard رزرو — patient-portal API." />
      <div className="grid max-w-lg gap-4 rounded-2xl border border-[var(--border)] p-5">
        <label className="text-sm">
          کلینیک
          <select className="mt-1 w-full rounded-xl border px-3 py-2" value={clinicId} onChange={(e) => setClinicId(e.target.value)}>
            <option value="">انتخاب…</option>
            {clinics.map((c) => (
              <option key={c.id} value={c.id}>{c.name}</option>
            ))}
          </select>
        </label>
        <label className="text-sm">
          پزشک
          <select className="mt-1 w-full rounded-xl border px-3 py-2" value={doctorId} onChange={(e) => setDoctorId(e.target.value)}>
            <option value="">انتخاب…</option>
            {doctors.filter((d) => !clinicId || d.clinic_id === clinicId).map((d) => (
              <option key={d.id} value={d.id}>{d.display_name}</option>
            ))}
          </select>
        </label>
        <Input type="datetime-local" value={start} onChange={(e) => setStart(e.target.value)} />
        <Input type="datetime-local" value={end} onChange={(e) => setEnd(e.target.value)} />
        <Button type="button" onClick={() => bookM.mutate()} disabled={!clinicId || !doctorId || !start || !end || bookM.isPending}>
          {bookM.isPending ? "در حال ثبت…" : "ثبت نوبت"}
        </Button>
      </div>
    </div>
  );
}

export function PatientMedicalHistory() {
  return (
    <PatientGate>
      {() => <MedicalRecordsResourcePage title="سوابق پزشکی" readOnly />}
    </PatientGate>
  );
}

export function PatientPrescriptions() {
  return (
    <PatientGate>
      {(ctx) => (
        <PatientPrescriptionsList tenantId={ctx.tenantId!} patientId={ctx.patientId!} />
      )}
    </PatientGate>
  );
}

function PatientPrescriptionsList({ tenantId, patientId }: { tenantId: string; patientId: string }) {
  const rxQ = useQuery({
    queryKey: ["healthcare", tenantId, "patient-rx", patientId],
    queryFn: () => healthcareApi.prescriptionOrders.list(tenantId),
    select: (rows) => rows.filter((r) => r.patient_id === patientId),
  });

  if (rxQ.isLoading) return <HealthcarePageLoader />;
  if (rxQ.error) return <HealthcarePageError error={rxQ.error} onRetry={() => rxQ.refetch()} />;

  return (
    <div>
      <PageHeader title="نسخه‌ها" />
      <div className="space-y-3">
        {(rxQ.data ?? []).map((o) => (
          <PrescriptionCard key={o.id} order={o} />
        ))}
      </div>
      {(rxQ.data ?? []).length === 0 ? <EmptyState title="نسخه‌ای نیست" /> : null}
    </div>
  );
}

export function PatientLabResults() {
  return (
    <PatientGate>
      {(ctx) => <PatientDocumentsList tenantId={ctx.tenantId!} patientId={ctx.patientId!} filter="lab" title="نتایج آزمایش" />}
    </PatientGate>
  );
}

export function PatientInvoices() {
  return <ExternalProvidersResourcePage kind="accounting" title="فاکتورها" />;
}

export function PatientPayments() {
  return <ExternalProvidersResourcePage kind="accounting" title="پرداخت‌ها" />;
}

export function PatientProfile() {
  return (
    <PatientGate>
      {(ctx) => <PatientProfileForm tenantId={ctx.tenantId!} patientId={ctx.patientId!} />}
    </PatientGate>
  );
}

function PatientProfileForm({ tenantId, patientId }: { tenantId: string; patientId: string }) {
  const profileQ = useQuery({
    queryKey: ["healthcare", tenantId, patientId, "portal-me"],
    queryFn: () => healthcareApi.patientPortal.me(tenantId, patientId),
  });
  const qc = useQueryClient();
  const [lang, setLang] = useState("fa");

  const updateM = useMutation({
    mutationFn: () =>
      healthcareApi.patientPortal.updateMe(tenantId, patientId, {
        preferred_language: lang,
        version: profileQ.data!.version,
      }),
    onSuccess: async () => {
      toast.success("ذخیره شد");
      await qc.invalidateQueries({ queryKey: ["healthcare", tenantId, patientId, "portal-me"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (profileQ.isLoading) return <HealthcarePageLoader />;
  if (profileQ.error) return <HealthcarePageError error={profileQ.error} onRetry={() => profileQ.refetch()} />;

  return (
    <div>
      <PageHeader title="پروفایل" />
      <div className="max-w-md space-y-3 rounded-2xl border p-5">
        <Input value={lang} onChange={(e) => setLang(e.target.value)} placeholder="زبان ترجیحی" />
        <Button type="button" onClick={() => updateM.mutate()} disabled={updateM.isPending}>ذخیره</Button>
      </div>
    </div>
  );
}

export function PatientFamily() {
  return <PatientsResourcePage title="اعضای خانواده" readOnly />;
}

export function PatientNotifications() {
  return (
    <PatientGate>
      {(ctx) => <PatientNotificationPrefs tenantId={ctx.tenantId!} patientId={ctx.patientId!} />}
    </PatientGate>
  );
}

function PatientNotificationPrefs({ tenantId, patientId }: { tenantId: string; patientId: string }) {
  const prefsQ = useQuery({
    queryKey: ["healthcare", tenantId, patientId, "notif-prefs"],
    queryFn: () => healthcareApi.patientPortal.notificationPreferences(tenantId, patientId),
  });
  const qc = useQueryClient();
  const upsertM = useMutation({
    mutationFn: (body: { channel: string; template_key: string; enabled: boolean }) =>
      healthcareApi.patientPortal.upsertNotificationPreference(tenantId, patientId, body),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["healthcare", tenantId, patientId, "notif-prefs"] }),
  });

  if (prefsQ.isLoading) return <HealthcarePageLoader />;

  return (
    <div>
      <PageHeader title="اعلان‌ها" description="ترجیحات notification-preferences API." />
      <DataTable
        columns={[
          { key: "channel", header: "کانال" },
          { key: "template_key", header: "قالب" },
          {
            key: "enabled",
            header: "فعال",
            render: (r) => (
              <Button
                type="button"
                size="sm"
                variant="outline"
                onClick={() =>
                  upsertM.mutate({
                    channel: String(r.channel),
                    template_key: String(r.template_key),
                    enabled: !r.enabled,
                  })
                }
              >
                {r.enabled ? "فعال" : "غیرفعال"}
              </Button>
            ),
          },
        ]}
        rows={(prefsQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={
          <EmptyState
            title="ترجیحی ثبت نشده"
            action={
              <Button
                type="button"
                onClick={() => upsertM.mutate({ channel: "sms", template_key: "appointment_reminder", enabled: true })}
              >
                افزودن پیش‌فرض
              </Button>
            }
          />
        }
      />
    </div>
  );
}

export function PatientMessages() {
  return <ExternalProvidersResourcePage kind="communication" title="پیام‌ها" />;
}

export function PatientFavorites() {
  return <SettingsResourcePage title="علاقه‌مندی‌ها" description="تنظیمات ذخیره‌شده workspace." />;
}

export function PatientReviews() {
  return (
    <PatientGate>
      {(ctx) => <PatientDocumentsList tenantId={ctx.tenantId!} patientId={ctx.patientId!} title="نظرات و اسناد" />}
    </PatientGate>
  );
}

function PatientDocumentsList({
  tenantId,
  patientId,
  title,
  filter,
}: {
  tenantId: string;
  patientId: string;
  title: string;
  filter?: string;
}) {
  const docsQ = useQuery({
    queryKey: ["healthcare", tenantId, patientId, "docs", filter],
    queryFn: () => healthcareApi.patientPortal.documents(tenantId, patientId),
    select: (rows) =>
      filter ? rows.filter((d) => String(d.document_type ?? "").includes(filter)) : rows,
  });
  const [open, setOpen] = useState(false);
  const [titleInput, setTitleInput] = useState("");
  const [fileRef, setFileRef] = useState("");
  const qc = useQueryClient();
  const createM = useMutation({
    mutationFn: () =>
      healthcareApi.patientPortal.createDocument(tenantId, patientId, {
        code: `DOC-${Date.now()}`,
        title: titleInput,
        storage_file_ref: fileRef,
        document_type: filter ?? "general",
      }),
    onSuccess: async () => {
      toast.success("ثبت شد");
      setOpen(false);
      await qc.invalidateQueries({ queryKey: ["healthcare", tenantId, patientId, "docs"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (docsQ.isLoading) return <HealthcarePageLoader />;

  return (
    <div>
      <PageHeader
        title={title}
        actions={
          <Button type="button" onClick={() => setOpen(true)}>بارگذاری سند</Button>
        }
      />
      <DataTable
        columns={[
          { key: "title", header: "عنوان" },
          { key: "code", header: "کد" },
          { key: "document_type", header: "نوع", render: (r) => String(r.document_type ?? "—") },
          { key: "storage_file_ref", header: "فایل", render: (r) => String(r.storage_file_ref ?? "—") },
        ]}
        rows={(docsQ.data ?? []) as unknown as Record<string, unknown>[]}
        empty={<EmptyState title="سندی ثبت نشده" />}
      />
      <Dialog open={open} onClose={() => setOpen(false)} title="سند جدید" size="sm">
        <div className="space-y-3">
          <Input value={titleInput} onChange={(e) => setTitleInput(e.target.value)} placeholder="عنوان" />
          <Input value={fileRef} onChange={(e) => setFileRef(e.target.value)} placeholder="storage_file_ref" />
        </div>
        <div className="mt-4 flex justify-end gap-2">
          <Button type="button" variant="outline" onClick={() => setOpen(false)}>انصراف</Button>
          <Button type="button" onClick={() => createM.mutate()} disabled={!titleInput || !fileRef}>ثبت</Button>
        </div>
      </Dialog>
    </div>
  );
}

export const PatientSettings = () => <SettingsResourcePage title="تنظیمات بیمار" />;
