"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  AlertCircle,
  CheckCircle2,
  Copy,
  Info,
  Play,
  Plus,
  Trash2,
  Webhook,
  Workflow as WorkflowIcon,
} from "lucide-react";
import { useRouter } from "next/navigation";
import { useMemo, useState } from "react";
import { Modal } from "@/components/modal";
import { PageHeader } from "@/components/page-header";
import {
  Badge,
  Button,
  EmptyState,
  Field,
  Input,
  Mono,
  Panel,
  PageLoader,
  Select,
  Textarea,
} from "@/components/ui";
import { type CompiledWorkflow, WorkflowBuilder } from "@/components/workflow-builder";
import { api, ApiError } from "@/lib/api";
import type { Workflow } from "@/lib/types";
import { can, useAuth } from "@/lib/auth";
import { cn, relativeTime } from "@/lib/utils";

const TEMPLATE = JSON.stringify(
  {
    nodes: [
      { id: "t1", type: "trigger", config: {} },
      { id: "c1", type: "condition", config: { expr: "{{ trigger.priority }} == 'high'" } },
      {
        id: "n1",
        type: "tool",
        config: { tool: "kb.search", args: { query: "{{ trigger.query }}" } },
      },
    ],
    edges: [
      { from: "t1", to: "c1" },
      { from: "c1", to: "n1", when: "true" },
    ],
  },
  null,
  2
);

const TRIGGER_HINTS: Record<string, string> = {
  manual: "Run on demand from this dashboard or the API.",
  webhook: "An HMAC-signed inbound URL is generated on save, then fire it to run.",
  schedule: "Runs on a cron schedule you set on the trigger below.",
  event: "Runs when another workflow emits a matching internal event.",
};

const NODE_TYPES = ["trigger", "agent", "tool", "condition", "transform", "approval", "delay"];

function CreateModal({ onClose }: { onClose: () => void }) {
  const qc = useQueryClient();
  const [name, setName] = useState("");
  const [trigger, setTrigger] = useState("manual");
  const [mode, setMode] = useState<"visual" | "json">("visual");
  const [compiled, setCompiled] = useState<CompiledWorkflow | null>(null);
  const [def, setDef] = useState(TEMPLATE);
  const [error, setError] = useState<string | null>(null);
  const [created, setCreated] = useState<{ url: string | null; secret: string | null } | null>(
    null
  );

  const parsed = useMemo(() => {
    try {
      const d = JSON.parse(def);
      return {
        ok: true,
        nodes: Array.isArray(d.nodes) ? d.nodes.length : 0,
        edges: Array.isArray(d.edges) ? d.edges.length : 0,
      };
    } catch {
      return { ok: false, nodes: 0, edges: 0 };
    }
  }, [def]);

  const canSubmit = mode === "visual" ? !!compiled?.valid : parsed.ok;

  const create = useMutation({
    mutationFn: () => {
      if (mode === "visual") {
        if (!compiled?.valid) throw new ApiError(400, "Add at least one complete step.");
        return api.createWorkflow({
          name,
          definition: compiled.definition,
          trigger_type: trigger,
          trigger_config: compiled.triggerConfig,
        });
      }
      let definition: object;
      try {
        definition = JSON.parse(def);
      } catch {
        throw new ApiError(400, "Definition is not valid JSON");
      }
      return api.createWorkflow({ name, definition, trigger_type: trigger });
    },
    onSuccess: async (res) => {
      await qc.invalidateQueries({ queryKey: ["workflows"] });
      if (res.webhook_url) setCreated({ url: res.webhook_url, secret: res.webhook_secret });
      else onClose();
    },
    onError: (e) => setError(e instanceof ApiError ? e.message : "Failed"),
  });

  if (created) {
    return (
      <Modal
        open
        onClose={onClose}
        title="Webhook created"
        description="Copy the signing secret now. It won't be shown again."
      >
        <div className="space-y-3">
          <Field label="Inbound URL">
            <div className="flex items-center gap-2 rounded-lg border border-line bg-ink/60 px-3 py-2 font-mono text-xs text-muted">
              <span className="flex-1 truncate">{created.url}</span>
              <button onClick={() => navigator.clipboard.writeText(created.url ?? "")}>
                <Copy className="h-3.5 w-3.5" />
              </button>
            </div>
          </Field>
          <Field label="HMAC secret">
            <div className="flex items-center gap-2 rounded-lg border border-accent/30 bg-accent/5 px-3 py-2 font-mono text-xs text-accent">
              <span className="flex-1 truncate">{created.secret}</span>
              <button onClick={() => navigator.clipboard.writeText(created.secret ?? "")}>
                <Copy className="h-3.5 w-3.5" />
              </button>
            </div>
          </Field>
          <div className="flex justify-end">
            <Button variant="primary" onClick={onClose}>
              Done
            </Button>
          </div>
        </div>
      </Modal>
    );
  }

  return (
    <Modal
      open
      onClose={onClose}
      title="New workflow"
      description="Chain steps together. Each step runs after the one above it."
      className="max-w-3xl"
    >
      <form
        className="space-y-5"
        onSubmit={(e) => {
          e.preventDefault();
          setError(null);
          create.mutate();
        }}
      >
        <div className="grid gap-4 sm:grid-cols-2">
          <Field label="Name">
            <Input
              required
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="Triage inbound"
            />
          </Field>
          <Field label="Trigger">
            <Select value={trigger} onChange={(e) => setTrigger(e.target.value)}>
              <option value="manual">Manual</option>
              <option value="webhook">Webhook (signed)</option>
              <option value="schedule">Schedule (cron)</option>
              <option value="event">Event</option>
            </Select>
          </Field>
        </div>

        <div className="flex items-start gap-2 rounded-lg border border-line bg-ink/40 px-3 py-2 text-xs text-muted">
          <Info className="mt-0.5 h-3.5 w-3.5 shrink-0 text-accent" />
          <span>{TRIGGER_HINTS[trigger]}</span>
        </div>

        <div>
          <div className="mb-2 flex items-center justify-between gap-3">
            <span className="eyebrow">Steps</span>
            <div className="flex rounded-lg border border-line p-0.5">
              {(["visual", "json"] as const).map((m) => (
                <button
                  key={m}
                  type="button"
                  onClick={() => {
                    if (m === "json" && compiled)
                      setDef(JSON.stringify(compiled.definition, null, 2));
                    setMode(m);
                  }}
                  className={cn(
                    "rounded-md px-2.5 py-1 text-[11px] font-medium transition-colors",
                    mode === m ? "bg-surface-2 text-fg" : "text-muted hover:text-fg"
                  )}
                >
                  {m === "visual" ? "Builder" : "Advanced (JSON)"}
                </button>
              ))}
            </div>
          </div>

          {mode === "visual" ? (
            <WorkflowBuilder trigger={trigger} onChange={setCompiled} />
          ) : (
            <div>
              <div className="mb-1.5 flex items-center justify-end gap-3">
                {parsed.ok ? (
                  <span className="flex items-center gap-1 font-mono text-[11px] text-success">
                    <CheckCircle2 className="h-3.5 w-3.5" /> {parsed.nodes} nodes · {parsed.edges}{" "}
                    edges
                  </span>
                ) : (
                  <span className="flex items-center gap-1 font-mono text-[11px] text-danger">
                    <AlertCircle className="h-3.5 w-3.5" /> invalid JSON
                  </span>
                )}
                <button
                  type="button"
                  disabled={!parsed.ok}
                  onClick={() => setDef(JSON.stringify(JSON.parse(def), null, 2))}
                  className="text-[11px] text-muted transition-colors hover:text-fg disabled:opacity-40"
                >
                  Format
                </button>
                <button
                  type="button"
                  onClick={() => setDef(TEMPLATE)}
                  className="text-[11px] text-muted transition-colors hover:text-fg"
                >
                  Reset
                </button>
              </div>
              <Textarea
                rows={14}
                value={def}
                onChange={(e) => setDef(e.target.value)}
                spellCheck={false}
                className={cn(
                  "font-mono text-xs",
                  !parsed.ok && "border-danger/40 focus:border-danger/60"
                )}
              />
              <div className="mt-2 flex flex-wrap items-center gap-1.5">
                <span className="text-[11px] text-faint">Node types:</span>
                {NODE_TYPES.map((n) => (
                  <Mono key={n} className="text-faint">
                    {n}
                  </Mono>
                ))}
              </div>
              <p className="mt-1.5 text-xs text-faint">
                Sandboxed {"{{ }}"} templating over prior node outputs.
              </p>
            </div>
          )}
        </div>

        {error && (
          <div className="rounded-lg border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">
            {error}
          </div>
        )}
        <div className="flex justify-end gap-2">
          <Button type="button" variant="ghost" onClick={onClose}>
            Cancel
          </Button>
          <Button type="submit" variant="primary" loading={create.isPending} disabled={!canSubmit}>
            Create workflow
          </Button>
        </div>
      </form>
    </Modal>
  );
}

export default function WorkflowsPage() {
  const { role } = useAuth();
  const qc = useQueryClient();
  const router = useRouter();
  const workflows = useQuery({ queryKey: ["workflows"], queryFn: api.listWorkflows });
  const [modal, setModal] = useState(false);

  const runNow = async (wf: Workflow) => {
    const res = await api.runWorkflow(wf.id, {});
    router.push(`/runs/${res.run.id}`);
  };

  return (
    <div>
      <PageHeader
        eyebrow="Build"
        title="Workflows"
        description="Multi-step automations with triggers, conditions, and human approval gates."
        actions={
          can(role, "build") && (
            <Button variant="primary" onClick={() => setModal(true)}>
              <Plus className="h-4 w-4" /> New workflow
            </Button>
          )
        }
      />

      {workflows.isLoading ? (
        <PageLoader />
      ) : (workflows.data ?? []).length === 0 ? (
        <EmptyState
          icon={<WorkflowIcon className="h-8 w-8" />}
          title="No workflows yet"
          description="Compose agents and tools into a graph, triggered manually, by webhook, or on a schedule."
          action={
            can(role, "build") && (
              <Button variant="primary" onClick={() => setModal(true)}>
                <Plus className="h-4 w-4" /> New workflow
              </Button>
            )
          }
        />
      ) : (
        <div className="grid gap-4 sm:grid-cols-2">
          {(workflows.data ?? []).map((wf) => (
            <Panel key={wf.id}>
              <div className="flex items-start justify-between">
                <div className="flex items-center gap-3">
                  <div className="flex h-10 w-10 items-center justify-center rounded-xl border border-line bg-surface-2 text-accent">
                    <WorkflowIcon className="h-5 w-5" />
                  </div>
                  <div>
                    <div className="font-display text-lg font-semibold text-fg">{wf.name}</div>
                    <div className="mt-0.5 flex items-center gap-1.5">
                      <Badge tone={wf.trigger_type === "webhook" ? "info" : "neutral"}>
                        {wf.trigger_type === "webhook" && <Webhook className="h-3 w-3" />}
                        {wf.trigger_type}
                      </Badge>
                      <Mono className="text-faint">
                        {wf.definition_json.nodes?.length ?? 0} nodes
                      </Mono>
                    </div>
                  </div>
                </div>
              </div>
              <div className="mt-4 flex items-center justify-between border-t border-line pt-4">
                <span className="text-xs text-faint">Created {relativeTime(wf.created_at)}</span>
                <div className="flex gap-2">
                  {can(role, "build") && (
                    <button
                      onClick={async () => {
                        if (!confirm("Delete this workflow?")) return;
                        await api.deleteWorkflow(wf.id);
                        await qc.invalidateQueries({ queryKey: ["workflows"] });
                      }}
                      className="rounded-lg p-2 text-faint hover:bg-surface-2 hover:text-danger"
                    >
                      <Trash2 className="h-4 w-4" />
                    </button>
                  )}
                  {can(role, "run") && wf.trigger_type === "manual" && (
                    <Button size="sm" variant="outline" onClick={() => runNow(wf)}>
                      <Play className="h-3.5 w-3.5" /> Run
                    </Button>
                  )}
                </div>
              </div>
            </Panel>
          ))}
        </div>
      )}

      {modal && <CreateModal onClose={() => setModal(false)} />}
    </div>
  );
}
