"use client";

import * as React from "react";
import { DownloadIcon, PlusIcon } from "lucide-react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { AsyncBadge, EtimsBadge, JobStatus, type AsyncState, type JobState } from "@/components/medora/async-status";
import { NeedsConnection, OfflineBanner, OfflineStatus, PageError, PanelError, type PageErrorKind } from "@/components/medora/errors";
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";

const KINDS: { value: PageErrorKind; label: string }[] = [
  { value: "not-found", label: "Not found" },
  { value: "no-access", label: "No access" },
  { value: "record-not-found", label: "Record gone" },
  { value: "failed", label: "Page failed" },
  { value: "signed-out", label: "Signed out" },
];

function PageErrors() {
  const [kind, setKind] = React.useState<PageErrorKind>("not-found");
  const [touched, setTouched] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const action =
    kind === "record-not-found"
      ? { label: "Back to sales", href: "#" }
      : kind === "signed-out"
        ? { label: "Sign in", href: "#" }
        : kind === "failed"
          ? {
              label: "Try again",
              busy,
              onClick: () => {
                setBusy(true);
                setTimeout(() => setBusy(false), 1200);
              },
            }
          : undefined;
  return (
    <Example title="Page errors" description="Inside the normal app frame; centred; what happened, what to do, one action. Focus moves to the title" bare>
      <div className="border-b border-border px-4 py-3">
        <ToggleGroup variant="outline" size="sm" spacing={0} aria-label="Error" value={[kind]} onValueChange={(v: string[]) => {
            if (!v[0]) return;
            setKind(v[0] as PageErrorKind);
            setTouched(true);
          }} className="flex-wrap">
          {KINDS.map((k) => (
            <ToggleGroupItem key={k.value} value={k.value}>
              {k.label}
            </ToggleGroupItem>
          ))}
        </ToggleGroup>
      </div>
      <PageError
        kind={kind}
        title={kind === "record-not-found" ? "This sale no longer exists" : undefined}
        action={action}
        reference={kind === "failed" ? "REQ-7F3K-21Q" : undefined}
        autoFocus={touched}
      />
    </Example>
  );
}

function PanelErrors() {
  const [attempts, setAttempts] = React.useState(1);
  const [retrying, setRetrying] = React.useState(false);
  return (
    <div className="grid gap-4 md:grid-cols-2">
      <Example title="Panel error" description="Only this panel failed; its title and As at stay. Fails three times here, then adds who to contact" bare>
        <div className="border-b border-border px-4 py-2.5">
          <p className="text-sm font-semibold">Sales by branch</p>
          <p className="text-xs text-muted-foreground">1–20 Oct 2026</p>
        </div>
        <PanelError
          what="sales by branch"
          attempts={attempts}
          retrying={retrying}
          reference="REQ-9A21-KX4"
          onRetry={() => {
            setRetrying(true);
            setTimeout(() => {
              setRetrying(false);
              setAttempts((a) => a + 1);
            }, 900);
          }}
        />
      </Example>
      <Example title="Next to it, still working" description="Other panels are unaffected">
        <p className="text-sm font-semibold">Top products</p>
        <ol className="mt-2 space-y-1 text-sm">
          {["Panadol 500 mg", "Amoxil 500 mg", "Brufen 400 mg"].map((p, i) => (
            <li key={p} className="flex justify-between">
              <span>
                {i + 1}. {p}
              </span>
              <span className="text-muted-foreground tabular-nums">{[412, 280, 196][i]} sold</span>
            </li>
          ))}
        </ol>
      </Example>
    </div>
  );
}

function Offline() {
  const [checking, setChecking] = React.useState(false);
  return (
    <Example title="Offline" description="Banner under the top bar, Offline status in the top bar, and server actions marked before use. Data on screen stays with its As at time" bare>
      <div className="flex items-center justify-between border-b border-border px-4 py-2">
        <span className="text-sm font-medium">Westlands Main</span>
        <OfflineStatus />
      </div>
      <OfflineBanner
        asAt="14:32"
        checking={checking}
        onRetry={() => {
          setChecking(true);
          setTimeout(() => setChecking(false), 1200);
        }}
      />
      <div className="flex flex-wrap items-start gap-3 p-4">
        <NeedsConnection>
          <Button disabled>
            <PlusIcon data-icon="inline-start" />
            New purchase order
          </Button>
        </NeedsConnection>
        <Button variant="outline">Print receipt</Button>
      </div>
    </Example>
  );
}

const STATES: { state: AsyncState; label: string; severe?: boolean }[] = [
  { state: "waiting", label: "Waiting for customer" },
  { state: "checking", label: "Checking with M-Pesa" },
  { state: "queued", label: "Queued" },
  { state: "done", label: "Paid" },
  { state: "attention", label: "Amount mismatch" },
  { state: "attention", label: "Rejected by KRA", severe: true },
  { state: "failed", label: "Not paid" },
];

function Jobs() {
  const [job, setJob] = React.useState<JobState>({ state: "idle" });
  const [rows, setRows] = React.useState(8400);
  const timer = React.useRef<ReturnType<typeof setInterval> | null>(null);
  const failNext = React.useRef(false);
  React.useEffect(() => () => void (timer.current && clearInterval(timer.current)), []);

  const start = () => {
    if (rows > 20000) return setJob({ state: "too-large", rows });
    toast.add({ title: "Your export is being prepared", description: "You can keep working." });
    let pct = 0;
    setJob({ state: "running", pct });
    timer.current = setInterval(() => {
      pct += 20;
      if (failNext.current && pct >= 60) {
        clearInterval(timer.current!);
        failNext.current = false;
        setJob({ state: "failed" });
        return;
      }
      if (pct >= 100) {
        clearInterval(timer.current!);
        setJob({ state: "ready", file: "sales-oct-2026.xlsx" });
        toast.add({ title: "Export ready", description: "sales-oct-2026.xlsx" });
      } else setJob({ state: "running", pct });
    }, 400);
  };

  return (
    <Example title="Background export" description="Started from the report header; the user keeps working. Ready keeps a Download link until it's used" bare>
      <div className="flex flex-wrap items-start justify-between gap-3 px-4 py-3">
        <div>
          <p className="text-base font-semibold">Sales report</p>
          <p className="text-xs text-muted-foreground">All branches · 1–20 Oct 2026 · {rows.toLocaleString("en-US")} rows</p>
        </div>
        <div className="flex flex-col items-end gap-2">
          <Button variant="outline" size="sm" onClick={start} disabled={job.state === "running"}>
            <DownloadIcon data-icon="inline-start" />
            {job.state === "running" ? "Preparing…" : "Export"}
          </Button>
          <JobStatus
            job={job}
            onDownload={() => {
              toast.add({ title: "Downloading sales-oct-2026.xlsx" });
              setJob({ state: "idle" });
            }}
            onRetry={start}
            onCancel={() => {
              if (timer.current) clearInterval(timer.current);
              setJob({ state: "idle" });
            }}
          />
        </div>
      </div>
      <div className="flex flex-wrap gap-2 border-t border-border px-4 py-2.5">
        <Button size="xs" variant="ghost" onClick={() => setRows((r) => (r > 20000 ? 8400 : 46200))}>
          {rows > 20000 ? "Use 8,400 rows" : "Use 46,200 rows"}
        </Button>
        <Button size="xs" variant="ghost" onClick={() => (failNext.current = true)}>
          Fail the next export
        </Button>
      </div>
    </Example>
  );
}

export function ErrorStatesSection() {
  return (
    <Section
      id="errors"
      title="Error states"
      description="Say what happened and what to do; keep what was typed; contain the error to the part that failed. Field errors are on the Forms page. Page errors replace the page content inside the frame; panel errors replace one panel; offline keeps data on screen with its As at time."
    >
      <PageErrors />
      <PanelErrors />
      <Offline />
    </Section>
  );
}

export function AsyncStatusSection() {
  return (
    <Section
      id="async"
      title="Async operation status"
      description="One model for everything that finishes later (M-Pesa, KRA eTIMS, exports): the same words and icons, stored on the record and shown in place, never only in a toast. The M-Pesa waiting states are on the till page."
    >
      <Example title="Shared states" description="Waiting, checking, queued, done, needs attention (amber, or red when rejected), failed. The spinner holds still under reduced motion" className="flex flex-wrap gap-2">
        {STATES.map((s) => (
          <AsyncBadge key={s.label} {...s} />
        ))}
      </Example>
      <Example title="KRA eTIMS on a sale" description="The sale completes first; the badge follows" className="flex flex-wrap gap-2">
        <EtimsBadge status="sending" />
        <EtimsBadge status="sent" />
        <EtimsBadge status="queued" />
        <EtimsBadge status="rejected" />
      </Example>
      <Jobs />
    </Section>
  );
}
