"use client";

import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { Copy, Pencil, Plus, Sparkles, Trash2, Workflow } from "lucide-react";
import { Badge, Button, ConfirmDialog, Dialog, EmptyState, Field, Input, PageHeader, Panel, Select, Skeleton } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { useSession } from "@/components/session";
import { TRIGGERS } from "@/components/bots/bot-reply-dialog";
import { api, ApiError } from "@/lib/api";
import { formatDateTime } from "@/lib/format";
import { useApi } from "@/lib/use-api";
import type { BotFlow, TriggerType } from "@/lib/types";

const nf = new Intl.NumberFormat("en-IN");

function NewFlowDialog({ onClose, onCreated }: { onClose: () => void; onCreated: (f: BotFlow, warnings: string[]) => void }) {
  const toast = useToast();
  const [title, setTitle] = useState("");
  const [tt, setTt] = useState<TriggerType>("is");
  const [subject, setSubject] = useState("");
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [busy, setBusy] = useState(false);
  async function create() {
    setBusy(true);
    setErrors({});
    try {
      const r = await api.post<{ data: BotFlow; warnings: string[] }>("/bot-flows", { title, trigger_type: tt, trigger_subject: tt === "welcome" ? undefined : subject });
      onCreated(r.data, r.warnings ?? []);
    } catch (e) {
      if (e instanceof ApiError && Object.keys(e.fields).length) setErrors(e.fields);
      else toast("error", (e as Error).message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <Dialog
      open
      onClose={onClose}
      title="New bot flow"
      description="A flow is a guided conversation: questions, buttons and branches that run step by step."
      footer={
        <>
          <Button onClick={onClose}>Cancel</Button>
          <Button variant="primary" loading={busy} onClick={create}>
            Create and open builder
          </Button>
        </>
      }
    >
      <div className="space-y-4">
        <Field label="Title" htmlFor="nf-title" error={errors.title}>
          <Input id="nf-title" value={title} maxLength={120} onChange={(e) => setTitle(e.target.value)} invalid={!!errors.title} autoFocus placeholder="e.g. Order tracking" />
        </Field>
        <div className="grid gap-3 sm:grid-cols-[200px_1fr]">
          <Field label="Starts when the message" htmlFor="nf-tt">
            <Select id="nf-tt" value={tt} onChange={(e) => setTt(e.target.value as TriggerType)}>
              {TRIGGERS.map((t) => (
                <option key={t.value} value={t.value}>
                  {t.label}
                </option>
              ))}
            </Select>
          </Field>
          {tt !== "welcome" && (
            <Field label="Start trigger text" htmlFor="nf-ts" error={errors.trigger_subject}>
              <Input id="nf-ts" value={subject} maxLength={255} onChange={(e) => setSubject(e.target.value)} invalid={!!errors.trigger_subject} placeholder="e.g. Track my order" />
            </Field>
          )}
        </div>
      </div>
    </Dialog>
  );
}

export default function BotFlowsPage() {
  const router = useRouter();
  const toast = useToast();
  const { can } = useSession();
  const manage = can("bots.manage");
  const { data, loading, reload } = useApi<{ data: BotFlow[]; meta: { engine_enabled: boolean } }>("/bot-flows");
  const [creating, setCreating] = useState(false);
  const [deleting, setDeleting] = useState<BotFlow | null>(null);
  const [busy, setBusy] = useState<string | null>(null);
  const rows = data?.data ?? [];
  // Optimistic switch state until the reloaded row changes.
  const [flips, setFlips] = useState<Record<number, { value: BotFlow["status"]; base: BotFlow["status"] }>>({});
  const shown = (f: BotFlow) => (flips[f.id] && flips[f.id].base === f.status ? flips[f.id].value : f.status);

  async function toggle(f: BotFlow) {
    const next = f.status === "active" ? "inactive" : "active";
    setBusy(`s${f.id}`);
    setFlips((m) => ({ ...m, [f.id]: { value: next, base: f.status } }));
    try {
      await api.post(`/bot-flows/${f.id}/status`, { status: next });
      toast("success", next === "active" ? `${f.title} is on` : `${f.title} is off; conversations in progress were stopped`);
      reload();
    } catch (e) {
      setFlips((m) => {
        const copy = { ...m };
        delete copy[f.id];
        return copy;
      });
      toast("error", (e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  async function example() {
    setBusy("example");
    try {
      const r = await api.post<{ data: BotFlow }>("/bot-flows/example");
      router.push(`/bot-flows/${r.data.id}`);
    } catch (e) {
      toast("error", (e as Error).message);
      setBusy(null);
    }
  }
  async function duplicate(f: BotFlow) {
    try {
      await api.post(`/bot-flows/${f.id}/duplicate`);
      toast("success", `Copied ${f.title}`);
      reload();
    } catch (e) {
      toast("error", (e as Error).message);
    }
  }
  async function remove() {
    if (!deleting) return;
    setBusy("delete");
    try {
      await api.delete(`/bot-flows/${deleting.id}`);
      toast("success", "Flow deleted");
      setDeleting(null);
      reload();
    } catch (e) {
      toast("error", (e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  return (
    <>
      <PageHeader
        title="Bot flows"
        description="Guided conversations with buttons, questions and branches, built on a visual canvas."
        actions={
          manage && (
            <div className="flex flex-wrap gap-2">
              <Button icon={<Sparkles className="size-4" />} loading={busy === "example"} onClick={example}>
                Add example flow
              </Button>
              <Button variant="primary" icon={<Plus className="size-4" />} onClick={() => setCreating(true)}>
                New flow
              </Button>
            </div>
          )
        }
      />
      <Panel>
        {!data && loading ? (
          <div className="space-y-3 p-5">
            {[0, 1].map((i) => (
              <Skeleton key={i} className="h-12 w-full" />
            ))}
          </div>
        ) : rows.length === 0 ? (
          <EmptyState
            icon={<Workflow />}
            title="No flows yet"
            body="Start from the account-support example, or build your own from scratch."
            action={
              manage && (
                <Button variant="primary" icon={<Sparkles className="size-4" />} loading={busy === "example"} onClick={example}>
                  Add example flow
                </Button>
              )
            }
          />
        ) : (
          <div className="relative overflow-x-auto">
            <table className="w-full min-w-[720px] text-sm">
              <thead className="border-b border-line text-left text-[13px] text-muted">
                <tr>
                  <th className="px-5 py-3 font-medium">Flow</th>
                  <th className="px-3 py-3 font-medium">Start trigger</th>
                  <th className="px-3 py-3 font-medium">Published</th>
                  <th className="px-3 py-3 text-right font-medium">Runs</th>
                  <th className="px-3 py-3 font-medium">Status</th>
                  <th className="px-5 py-3 text-right font-medium">
                    <span className="sr-only">Actions</span>
                  </th>
                </tr>
              </thead>
              <tbody className="divide-y divide-line">
                {rows.map((f) => (
                  <tr key={f.id} className="group relative hover:bg-paper/60">
                    <td className="px-5 py-3">
                      <Link href={`/bot-flows/${f.id}`} className="font-medium text-ink after:absolute after:inset-0 group-hover:text-teal">
                        {f.title}
                      </Link>
                      <p className="text-[13px] text-muted">
                        {f.step_count} steps, edited {formatDateTime(f.updated_at)}
                      </p>
                    </td>
                    <td className="px-3 py-3">
                      <span className="text-[13px] text-muted">{f.trigger_label}</span>
                      {f.trigger_subject && <span className="block font-medium">“{f.trigger_subject}”</span>}
                    </td>
                    <td className="px-3 py-3">
                      {f.published_version ? (
                        <span>
                          Version {f.published_version}
                          {f.has_unpublished_changes && <span className="block text-xs text-amber">Draft has changes</span>}
                        </span>
                      ) : (
                        <span className="text-muted">Not yet</span>
                      )}
                    </td>
                    <td className="tabular px-3 py-3 text-right">
                      {f.runs?.total ? (
                        <span title={`${f.runs.completed} completed, ${f.runs.handed_off} handed off, ${f.runs.failed} failed`}>
                          {nf.format(f.runs.total)}
                          {f.runs.active > 0 && <span className="block text-xs text-teal">{nf.format(f.runs.active)} in progress</span>}
                        </span>
                      ) : (
                        <span className="text-muted">—</span>
                      )}
                    </td>
                    <td className="px-3 py-3">
                      {manage ? (
                        <label className="relative z-10 inline-flex cursor-pointer items-center gap-2" title={f.published_version ? undefined : "Publish the flow first"}>
                          <input
                            type="checkbox"
                            role="switch"
                            className="size-4 accent-teal"
                            aria-label={`${f.title} on`}
                            checked={shown(f) === "active"}
                            disabled={busy === `s${f.id}` || (!f.published_version && f.status !== "active")}
                            onChange={() => toggle(f)}
                          />
                          <span className="text-[13px]">{shown(f) === "active" ? "On" : "Off"}</span>
                        </label>
                      ) : (
                        <Badge tone={f.status === "active" ? "teal" : "neutral"}>{f.status === "active" ? "On" : "Off"}</Badge>
                      )}
                    </td>
                    <td className="px-5 py-3">
                      <div className="relative z-10 flex justify-end gap-1">
                        <Link href={`/bot-flows/${f.id}`} className="rounded p-1.5 text-muted hover:bg-paper hover:text-teal" aria-label={`Open ${f.title} in the builder`} title="Open builder">
                          <Pencil className="size-4" />
                        </Link>
                        {manage && (
                          <>
                            <button onClick={() => duplicate(f)} className="rounded p-1.5 text-muted hover:bg-paper hover:text-teal" aria-label={`Duplicate ${f.title}`} title="Duplicate">
                              <Copy className="size-4" />
                            </button>
                            <button onClick={() => setDeleting(f)} className="rounded p-1.5 text-muted hover:bg-paper hover:text-brick" aria-label={`Delete ${f.title}`} title="Delete">
                              <Trash2 className="size-4" />
                            </button>
                          </>
                        )}
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </Panel>
      {creating && (
        <NewFlowDialog
          onClose={() => setCreating(false)}
          onCreated={(f, w) => {
            if (w.length) toast("error", w[0]);
            router.push(`/bot-flows/${f.id}`);
          }}
        />
      )}
      <ConfirmDialog open={!!deleting} title="Delete this flow?" message={`“${deleting?.title}” and its published versions will be removed.`} confirmLabel="Delete" loading={busy === "delete"} onConfirm={remove} onClose={() => setDeleting(null)} />
    </>
  );
}
