"use client";

import * as React from "react";
import Link from "next/link";
import { ArrowRightIcon } from "lucide-react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { useUnsavedChangesGuard } from "@/components/medora/unsaved-changes";
import { Button } from "@/components/ui/button";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { toast } from "@/components/ui/toast";

const SAVED = { name: "Grace Wambui", phone: "0722 111 222", creditLimit: "5000" };
const LABEL: Record<keyof typeof SAVED, string> = { name: "Name", phone: "Phone", creditLimit: "Credit limit" };

function EditCustomer() {
  const [saved, setSaved] = React.useState(SAVED);
  const [form, setForm] = React.useState(SAVED);
  const [tab, setTab] = React.useState("details");
  const [failSave, setFailSave] = React.useState(false);
  const [saving, setSaving] = React.useState(false);

  const changes = (Object.keys(form) as (keyof typeof SAVED)[]).filter((k) => form[k] !== saved[k]).map((k) => LABEL[k]);
  const dirty = changes.length > 0;

  const save = async () => {
    await new Promise((r) => setTimeout(r, 800));
    if (failSave) return false;
    setSaved(form);
    toast.add({ type: "success", title: "Customer saved", description: changes.join(", ") });
    return true;
  };

  const { guard, dialog } = useUnsavedChangesGuard({ dirty, changes, save, discard: () => setForm(saved) });
  const set = (k: keyof typeof SAVED) => (e: React.ChangeEvent<HTMLInputElement>) => setForm((f) => ({ ...f, [k]: e.target.value }));

  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-center gap-2 rounded-lg border border-dashed border-input p-2 text-sm">
        <span className="px-1 text-xs text-muted-foreground">Leave this form by:</span>
        <Link href="/design-system/data-display" className="inline-flex items-center gap-1 rounded-md px-2 py-1 font-medium text-primary hover:bg-muted">
          A link to Data display <ArrowRightIcon className="size-3.5" />
        </Link>
        <Link href="/design-system/actions" className="inline-flex items-center gap-1 rounded-md px-2 py-1 font-medium text-primary hover:bg-muted">
          A link to Actions <ArrowRightIcon className="size-3.5" />
        </Link>
        <span className="px-1 text-xs text-muted-foreground">· the sidebar · a reload (browser prompt)</span>
      </div>

      <Tabs value={tab} onValueChange={(v) => guard(() => setTab(String(v)))}>
        <TabsList>
          <TabsTrigger value="details">Details</TabsTrigger>
          <TabsTrigger value="statement">Statement</TabsTrigger>
        </TabsList>
      </Tabs>

      {tab === "details" ? (
        <FieldGroup className="gap-3">
          <div className="grid gap-3 sm:grid-cols-3">
            <Field>
              <FieldLabel htmlFor="uc-name">Name</FieldLabel>
              <Input id="uc-name" value={form.name} onChange={set("name")} />
            </Field>
            <Field>
              <FieldLabel htmlFor="uc-phone">Phone</FieldLabel>
              <Input id="uc-phone" value={form.phone} onChange={set("phone")} />
            </Field>
            <Field>
              <FieldLabel htmlFor="uc-limit">Credit limit (KES)</FieldLabel>
              <Input id="uc-limit" inputMode="numeric" className="tabular-nums" value={form.creditLimit} onChange={set("creditLimit")} />
            </Field>
          </div>
        </FieldGroup>
      ) : (
        <p className="rounded-lg bg-muted px-3 py-6 text-center text-sm text-muted-foreground">Statement for {saved.name}.</p>
      )}

      <div className="flex flex-wrap items-center justify-between gap-3 border-t border-border pt-3">
        <span className="text-sm text-muted-foreground">{dirty ? `Unsaved: ${changes.join(", ")}` : "All changes saved."}</span>
        <div className="flex items-center gap-3">
          <label className="flex cursor-pointer items-center gap-2 text-xs text-muted-foreground">
            <Switch checked={failSave} onCheckedChange={setFailSave} />
            Make saving fail
          </label>
          <Button variant="outline" disabled={!dirty} onClick={() => guard(() => {})}>
            Cancel
          </Button>
          <Button
            disabled={!dirty || saving}
            onClick={async () => {
              setSaving(true);
              const ok = await save();
              setSaving(false);
              if (!ok) toast.add({ type: "error", title: "Could not save", description: "Try again." });
            }}
          >
            Save
          </Button>
        </div>
      </div>
      {dialog}
    </div>
  );
}

export function UnsavedChangesSection() {
  return (
    <Section
      id="unsaved-guard"
      title="Unsaved-changes guard"
      description="A form with edits asks before they are lost: in-app links (including the sidebar), switching tabs and Cancel open “Leave without saving?” with Stay (default), Discard changes and Save and leave. Reload, closing the tab or typing a URL get the browser's own prompt. Save and leave only leaves if the save succeeds."
    >
      <Example
        title="Edit customer"
        description="Change a field, then try a link, the Statement tab, Cancel or the sidebar"
        code={`const { guard, dialog } = useUnsavedChangesGuard({ dirty, changes, save, discard: reset });

<Tabs onValueChange={(v) => guard(() => setTab(v))} />
<Button onClick={() => guard(closeForm)}>Cancel</Button>
{dialog}`}
      >
        <EditCustomer />
      </Example>
    </Section>
  );
}
