// Studio scene — design a new FlowMaster process and publish it to EA2.
import { useState } from "react";
import { useApp } from "../state/store";
import { api } from "../lib/api";
import { Branch, Play, Check, Close, Bot, User, Cog } from "../components/icons";

type NodeKind = "start" | "human_task" | "agent_task" | "service_task" | "end";

interface DraftNode {
  id: string;
  type: NodeKind;
  label: string;
}

interface DraftEdge {
  id: string;
  source: string;
  target: string;
}

const DEFAULT_NODES: DraftNode[] = [
  { id: "start", type: "start", label: "Request received" },
  { id: "review", type: "human_task", label: "Manager review" },
  { id: "approved", type: "end", label: "Approved" },
];
const DEFAULT_EDGES: DraftEdge[] = [
  { id: "e1", source: "start", target: "review" },
  { id: "e2", source: "review", target: "approved" },
];

const KIND_ICON: Record<NodeKind, (p: { size?: number }) => React.ReactElement> = {
  start: Branch,
  end: Branch,
  human_task: User,
  agent_task: Bot,
  service_task: Cog,
};

const ORG_ID = "a0000000-0000-0000-0000-000000000010";

export default function Studio() {
  const mode = useApp((s) => s.mode);
  const pushToast = useApp((s) => s.pushToast);
  const refreshLive = useApp((s) => s.refreshLive);
  const actor = useApp((s) => s.actor);
  const setScene = useApp((s) => s.setScene);

  const [name, setName] = useState("my-process-" + Math.random().toString(36).slice(2, 8));
  const [displayName, setDisplayName] = useState("My Process");
  const [hub, setHub] = useState("procurement");
  const [description, setDescription] = useState("Demo process designed in the Studio.");
  const [nodes, setNodes] = useState<DraftNode[]>(DEFAULT_NODES);
  const [edges, setEdges] = useState<DraftEdge[]>(DEFAULT_EDGES);
  const [publishing, setPublishing] = useState(false);
  const [lastResult, setLastResult] = useState<{ ok: boolean; key?: string; err?: string } | null>(null);

  const canPublish = mode === "live" && !!actor?.user_id;

  const addNode = () => {
    const idx = nodes.length;
    setNodes([...nodes, { id: `n${idx}`, type: "human_task", label: `New step ${idx}` }]);
  };

  const removeNode = (id: string) => {
    setNodes(nodes.filter((n) => n.id !== id));
    setEdges(edges.filter((e) => e.source !== id && e.target !== id));
  };

  const updateNode = (id: string, patch: Partial<DraftNode>) => {
    setNodes(nodes.map((n) => (n.id === id ? { ...n, ...patch } : n)));
  };

  const addEdge = () => {
    if (nodes.length < 2) return;
    const idx = edges.length;
    setEdges([...edges, { id: `e${idx + 1}`, source: nodes[0].id, target: nodes[nodes.length - 1].id }]);
  };

  const removeEdge = (id: string) => setEdges(edges.filter((e) => e.id !== id));

  const updateEdge = (id: string, patch: Partial<DraftEdge>) => {
    setEdges(edges.map((e) => (e.id === id ? { ...e, ...patch } : e)));
  };

  const publish = async () => {
    if (!canPublish) {
      pushToast("warn", "Switch to LIVE mode + sign in to publish a process.");
      return;
    }
    setPublishing(true);
    setLastResult(null);
    try {
      const r = await api.createProcess({
        name,
        display_name: displayName,
        label: displayName,
        description,
        hub,
        config: {
          org_id: ORG_ID,
          executable: true,
          nodes: nodes.map((n) => ({ id: n.id, type: n.type, label: n.label })),
          edges: edges.map((e) => ({ id: e.id, source: e.source, target: e.target })),
        },
      });
      pushToast("ok", `Published ${r.name} → ${r._key.slice(0, 8)}`);
      setLastResult({ ok: true, key: r._key });
      await refreshLive();
    } catch (e) {
      pushToast("err", `Publish failed: ${(e as Error).message.slice(0, 140)}`);
      setLastResult({ ok: false, err: (e as Error).message });
    } finally {
      setPublishing(false);
    }
  };

  const valid = nodes.length >= 2 && edges.length >= 1 && nodes.every((n) => n.label.trim().length > 0);

  return (
    <div className="studio">
      <header className="studio-head">
        <div>
          <div className="mc-hero-eyebrow"><Branch size={12} /> Process Studio</div>
          <h2 className="mc-hero-title">Design a new process</h2>
          <div className="mc-hero-sub">Hand-craft a typed FlowMaster process and publish it straight to EA2 on demo.flow-master.ai.</div>
        </div>
        <button className="btn btn-primary btn-lg" onClick={publish} disabled={!valid || publishing}>
          {publishing ? <span className="spin" /> : <Play size={13} />} Publish to EA2
          {!canPublish && <span className="preview-marker">live + sign-in required</span>}
        </button>
      </header>

      <div className="studio-grid">
        <section className="studio-panel">
          <h3 className="panel-h">Definition</h3>
          <label className="studio-field">
            <span>name (unique slug)</span>
            <input className="studio-input mono" value={name} onChange={(e) => setName(e.target.value)} />
          </label>
          <label className="studio-field">
            <span>display name</span>
            <input className="studio-input" value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
          </label>
          <label className="studio-field">
            <span>hub</span>
            <select className="studio-input" value={hub} onChange={(e) => setHub(e.target.value)}>
              <option value="procurement">procurement</option>
              <option value="finance">finance</option>
              <option value="people">people</option>
              <option value="service">service</option>
            </select>
          </label>
          <label className="studio-field">
            <span>description</span>
            <textarea className="studio-input" value={description} onChange={(e) => setDescription(e.target.value)} rows={3} />
          </label>
        </section>

        <section className="studio-panel">
          <h3 className="panel-h">
            Nodes
            <span className="panel-count">{nodes.length}</span>
            <button className="link-btn" style={{ marginLeft: "auto" }} onClick={addNode}>+ node</button>
          </h3>
          <div className="studio-rows">
            {nodes.map((n) => {
              const Icon = KIND_ICON[n.type] ?? Cog;
              return (
                <div key={n.id} className="studio-row">
                  <span className="studio-row-id mono">{n.id}</span>
                  <Icon size={13} />
                  <select className="studio-input" value={n.type} onChange={(e) => updateNode(n.id, { type: e.target.value as NodeKind })}>
                    <option value="start">start</option>
                    <option value="human_task">human_task</option>
                    <option value="agent_task">agent_task</option>
                    <option value="service_task">service_task</option>
                    <option value="end">end</option>
                  </select>
                  <input className="studio-input" value={n.label} onChange={(e) => updateNode(n.id, { label: e.target.value })} />
                  <button className="link-btn" onClick={() => removeNode(n.id)} title="Remove"><Close size={11} /></button>
                </div>
              );
            })}
          </div>
        </section>

        <section className="studio-panel">
          <h3 className="panel-h">
            Edges
            <span className="panel-count">{edges.length}</span>
            <button className="link-btn" style={{ marginLeft: "auto" }} onClick={addEdge}>+ edge</button>
          </h3>
          <div className="studio-rows">
            {edges.map((e) => (
              <div key={e.id} className="studio-row">
                <span className="studio-row-id mono">{e.id}</span>
                <select className="studio-input" value={e.source} onChange={(ev) => updateEdge(e.id, { source: ev.target.value })}>
                  {nodes.map((n) => <option key={n.id} value={n.id}>{n.id}</option>)}
                </select>
                <span className="mono" style={{ color: "var(--text-3)" }}>→</span>
                <select className="studio-input" value={e.target} onChange={(ev) => updateEdge(e.id, { target: ev.target.value })}>
                  {nodes.map((n) => <option key={n.id} value={n.id}>{n.id}</option>)}
                </select>
                <button className="link-btn" onClick={() => removeEdge(e.id)} title="Remove"><Close size={11} /></button>
              </div>
            ))}
          </div>
        </section>

        <section className="studio-panel">
          <h3 className="panel-h">JSON preview</h3>
          <pre className="raw-json"><code>{JSON.stringify({
            name, display_name: displayName, hub, description,
            kind: "definition", status: "published", version: 1,
            config: {
              org_id: ORG_ID, executable: true,
              nodes: nodes.map((n) => ({ id: n.id, type: n.type, label: n.label })),
              edges: edges.map((e) => ({ id: e.id, source: e.source, target: e.target })),
            },
          }, null, 2)}</code></pre>
          {lastResult && (
            <div className={`studio-result ${lastResult.ok ? "ok" : "err"}`}>
              {lastResult.ok ? (
                <>
                  <Check size={12} /> Published as <span className="mono">{lastResult.key?.slice(0, 12)}</span>
                  <button className="link-btn" onClick={() => setScene("mission")} style={{ marginLeft: "auto" }}>Open in Mission Control</button>
                </>
              ) : (
                <><Close size={12} /> <span className="mono">{lastResult.err?.slice(0, 200)}</span></>
              )}
            </div>
          )}
        </section>
      </div>
    </div>
  );
}
