import { useState, useEffect } from "react";
import { useApp } from "../state/store";
import { wizardApi, type BatchOperation } from "../lib/wizardApi";
import { Branch, Check, Close, ChevronRight } from "../components/icons";

type WizardStep = "Intake" | "Analyze" | "Generate" | "Validate" | "Draft saved" | "Publish";

const STEPS: WizardStep[] = ["Intake", "Analyze", "Generate", "Validate", "Draft saved", "Publish"];

interface DraftState {
  step: WizardStep;
  flowKey?: string;
  name: string;
  description: string;
  nodes: any[];
  edges: any[];
  fields: { name: string; type: string }[];
  rules: string[];
}

export default function Wizard() {
  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 canPublish = mode === "live" && !!actor?.user_id;

  const [draft, setDraft] = useState<DraftState>(() => {
    try {
      const stored = localStorage.getItem("fm.mc.wizard.draft");
      if (stored) return JSON.parse(stored);
    } catch {}
    return {
      step: "Intake",
      name: "",
      description: "",
      nodes: [],
      edges: [],
      fields: [],
      rules: []
    };
  });

  const [working, setWorking] = useState(false);
  const [publishedKey, setPublishedKey] = useState<string | null>(null);

  useEffect(() => {
    localStorage.setItem("fm.mc.wizard.draft", JSON.stringify(draft));
  }, [draft]);

  const updateDraft = (patch: Partial<DraftState>) => {
    setDraft(d => ({ ...d, ...patch }));
  };

  const handleIntakeSubmit = async () => {
    if (!draft.description) return;
    setWorking(true);
    try {
      const slug = `process_${Date.now()}`;
      const res = await wizardApi.createDraft({
        name: slug,
        display_name: draft.name || "Untitled Process",
        description: draft.description,
        source_context: "EA2_DRAFT_PROCESS:process_creation",
        config: {
          wizard: {
            marker: "EA2_DRAFT_PROCESS",
            maxDepth: 5,
            maxNodes: 40,
            chat: [],
            uploads: [],
            panelState: {},
            debug: []
          }
        }
      });
      
      // Auto-generate basic 5-step template
      const templateNodes = [
        { _key: "n1", kind: "step", display_name: "Capture request details", dispatch_kind: "human" },
        { _key: "n2", kind: "step", display_name: "Validate requirements", dispatch_kind: "agent", agent_capability: "evaluate_business_rule" },
        { _key: "n3", kind: "step", display_name: "Prepare work package", dispatch_kind: "agent", agent_capability: "process_design_assistant" },
        { _key: "n4", kind: "step", display_name: "Review and approve", dispatch_kind: "human" },
        { _key: "n5", kind: "step", display_name: "Close out process", dispatch_kind: "human" }
      ];
      
      updateDraft({ 
        flowKey: res._key, 
        step: "Analyze",
        nodes: templateNodes 
      });
      pushToast("ok", "Draft created in EA2");
    } catch (err: any) {
      pushToast("err", `Failed to create draft: ${err.message}`);
    } finally {
      setWorking(false);
    }
  };

  const handleStructureSave = async () => {
    if (!draft.flowKey || !actor) return;
    setWorking(true);
    try {
      const stepCreateOps: BatchOperation[] = draft.nodes.map(n =>
        wizardApi.ops.createStep({
          display_name: n.display_name,
          dispatch_kind: n.dispatch_kind,
          agent_capability: n.agent_capability,
        })
      );
      const viewCreateOps: BatchOperation[] = draft.nodes.map(n =>
        wizardApi.ops.createView({ display_name: n.display_name })
      );
      const versionCreateOp: BatchOperation = wizardApi.ops.createVersion(draft.name || "Process");
      const allCreateOps = [...stepCreateOps, ...viewCreateOps, versionCreateOp];

      const createRes = await wizardApi.applyBatch(draft.flowKey, allCreateOps, actor);
      const createdOps: any[] = createRes?.result?.ops || [];
      const stepKeys = createdOps.slice(0, draft.nodes.length).map(o => o.key);
      const viewKeys = createdOps.slice(draft.nodes.length, draft.nodes.length * 2).map(o => o.key);
      const versionKey = createdOps[createdOps.length - 1]?.key;
      const nodesWithKeys = draft.nodes.map((n, i) => ({ ...n, _key: stepKeys[i] || n._key, viewKey: viewKeys[i] }));

      const wireOps: BatchOperation[] = [
        ...nodesWithKeys.map((n, _i) => wizardApi.ops.childEdge(draft.flowKey!, n._key)),
        ...nodesWithKeys.map(n => wizardApi.ops.dispatchEdge(n._key)),
        ...nodesWithKeys.map(n => wizardApi.ops.presentationEdge(n._key, n.viewKey)),
      ];
      if (versionKey) wireOps.push(wizardApi.ops.governsEdge(versionKey, draft.flowKey!));
      if (wireOps.length) await wizardApi.applyBatch(draft.flowKey, wireOps, actor);

      updateDraft({ step: "Generate", nodes: nodesWithKeys });
      pushToast("ok", `Saved ${stepKeys.length} steps with views and version to EA2`);
    } catch (err: any) {
      pushToast("err", `Save failed: ${err.message}`);
    } finally {
      setWorking(false);
    }
  };

  const handleDataSave = async () => {
    if (!draft.flowKey || !actor) return;
    setWorking(true);
    try {
      await wizardApi.updateDraftConfig(draft.flowKey, {
         config: { wizard: { panelState: { fields: draft.fields } } }
      });

      if (draft.fields.length > 0 && draft.nodes.length > 0) {
        const token = sessionStorage.getItem("fm.mc.token.v1") || "";
        const oldEdgeKeys: string[] = [];
        for (const n of draft.nodes) {
          try {
            const r = await fetch(
              `${(await import("../lib/api")).api.config.baseUrl}/api/ea2/edges/defines?from=flow/${n._key}&limit=50`,
              { headers: { Authorization: `Bearer ${token}` } },
            );
            if (!r.ok) continue;
            const items = ((await r.json())?.items || []) as any[];
            for (const e of items) {
              if (e?.role === "presentation" && e?._key) oldEdgeKeys.push(e._key);
            }
          } catch { /* ignore */ }
        }

        const replaceOps: BatchOperation[] = draft.nodes.map(n =>
          wizardApi.ops.createView({ display_name: n.display_name, fields: draft.fields })
        );
        const res = await wizardApi.applyBatch(draft.flowKey, replaceOps, actor);
        const newViewKeys = (res?.result?.ops || []).map((o: any) => o.key);

        const wireOps: BatchOperation[] = [
          ...oldEdgeKeys.map((k): BatchOperation => ({ op: "delete_edge", edge_coll: "defines", key: k })),
          ...draft.nodes.map((n, i) => wizardApi.ops.presentationEdge(n._key, newViewKeys[i])),
        ];
        if (wireOps.length) await wizardApi.applyBatch(draft.flowKey, wireOps, actor);
        updateDraft({ nodes: draft.nodes.map((n, i) => ({ ...n, viewKey: newViewKeys[i] })) });
      }

      updateDraft({ step: "Validate" });
      pushToast("ok", `Saved ${draft.fields.length} fields onto every step's form`);
    } catch (err: any) {
      pushToast("err", `Save failed: ${err.message}`);
    } finally {
      setWorking(false);
    }
  };

  const handleRulesSave = async () => {
    if (!draft.flowKey || !actor) return;
    setWorking(true);
    try {
       await wizardApi.updateDraftConfig(draft.flowKey, {
         config: { wizard: { panelState: { rules: draft.rules } } }
      });
      updateDraft({ step: "Draft saved" });
      pushToast("ok", "Rules saved");
    } catch (err: any) {
      pushToast("err", `Save failed: ${err.message}`);
    } finally {
      setWorking(false);
    }
  };

  const handlePublish = async () => {
    if (!draft.flowKey || !actor) return;
    setWorking(true);
    try {
      const ops: BatchOperation[] = [wizardApi.ops.publishFlow(draft.flowKey)];
      await wizardApi.applyBatch(draft.flowKey, ops, actor);
      updateDraft({ step: "Publish" });
      setPublishedKey(draft.flowKey);
      pushToast("ok", "Process published successfully!");
      refreshLive();
    } catch (err: any) {
      pushToast("err", `Publish failed: ${err.message}`);
    } finally {
      setWorking(false);
    }
  };
  
  const handleStartInstance = async () => {
    if(!publishedKey) return;
    setWorking(true);
    try {
        await wizardApi.startInstance(publishedKey);
        pushToast("ok", "New instance started!");
        setScene("mission");
    } catch(err:any) {
        pushToast("err", `Failed to start: ${err.message}`);
    } finally {
        setWorking(false);
    }
  }

  const STEP_LABELS: Record<WizardStep, string> = {
    Intake: "Describe",
    Analyze: "Steps",
    Generate: "Form fields",
    Validate: "Rules",
    "Draft saved": "Review",
    Publish: "Done",
  };

  const renderStepNav = () => (
    <div className="wizard-progress">
      {STEPS.map((step, i) => {
        const isActive = step === draft.step;
        const isPast = STEPS.indexOf(step) < STEPS.indexOf(draft.step);
        const isDone = isPast || draft.step === "Publish";
        return (
          <div key={step} className={`wizard-step-marker ${isActive ? "active" : ""} ${isPast ? "past" : ""}`}>
            <span className={`step-num ${isDone ? "step-num-done" : ""}`}>
              {isDone ? <Check size={11} /> : i + 1}
            </span>
            <span className="step-label">{STEP_LABELS[step]}</span>
            {i < STEPS.length - 1 && <ChevronRight size={12} className="step-chevron" />}
          </div>
        );
      })}
    </div>
  );

  const renderGraphPreview = () => (
    <div className="wizard-preview-section">
      <div className="wizard-preview-label">Flow · {draft.nodes.length} step{draft.nodes.length === 1 ? "" : "s"}</div>
      <div className="wizard-preview-graph">
        {draft.nodes.map((n, i) => (
          <div key={n._key || i} className="wizard-graph-node">
            <div className={`wizard-graph-bubble kind-${n.dispatch_kind || "human"}`}>
              <span className="wizard-graph-idx">{i + 1}</span>
              <span className="wizard-graph-name">{n.display_name || "Untitled"}</span>
            </div>
            <div className="wizard-graph-meta">
              {({ human: "Manual", agent: "Assistant", system: "System" } as Record<string, string>)[n.dispatch_kind || "human"]}
            </div>
            {i < draft.nodes.length - 1 && <div className="wizard-graph-edge" aria-hidden />}
          </div>
        ))}
      </div>
    </div>
  );

  const renderFormPreview = () => (
    <div className="wizard-preview-section">
      <div className="wizard-preview-label">Form preview · what users will fill in</div>
      <div className="wizard-form-preview">
        {draft.fields.filter((f) => f.name).length === 0 ? (
          <div className="wizard-preview-empty">Add fields on the left to see the form here.</div>
        ) : (
          draft.fields.filter((f) => f.name).map((f, i) => (
            <div key={i} className="wizard-form-field">
              <label className="wizard-form-label">{f.name}</label>
              {f.type === "boolean" ? (
                <select className="wizard-form-input" disabled defaultValue=""><option value="">Yes / No</option></select>
              ) : f.type === "number" ? (
                <input className="wizard-form-input" type="number" placeholder="0" disabled />
              ) : (
                <input className="wizard-form-input" type="text" placeholder={`Enter ${f.name.toLowerCase()}`} disabled />
              )}
            </div>
          ))
        )}
      </div>
    </div>
  );

  const renderRulesPreview = () => (
    <div className="wizard-preview-section">
      <div className="wizard-preview-label">Rules · {draft.rules.filter((r) => r.trim()).length}</div>
      <ul className="wizard-preview-rules">
        {draft.rules.filter((r) => r.trim()).map((r, i) => <li key={i}>{r}</li>)}
        {draft.rules.filter((r) => r.trim()).length === 0 && (
          <li className="wizard-preview-empty">No rules typed yet</li>
        )}
      </ul>
    </div>
  );

  const renderPreviewPane = () => {
    if (draft.nodes.length === 0 && draft.fields.length === 0 && draft.rules.length === 0) return null;
    return (
      <aside className="wizard-preview">
        <div className="wizard-preview-head">
          <span className="mc-hero-eyebrow">Live preview</span>
          <div className="wizard-preview-title">{draft.name || "Untitled process"}</div>
          {draft.description && <div className="wizard-preview-desc">{draft.description.slice(0, 140)}</div>}
        </div>

        {(draft.step === "Analyze" || draft.step === "Generate" || draft.step === "Validate" || draft.step === "Draft saved") && draft.nodes.length > 0 && renderGraphPreview()}
        {(draft.step === "Generate" || draft.step === "Validate" || draft.step === "Draft saved") && renderFormPreview()}
        {(draft.step === "Validate" || draft.step === "Draft saved") && renderRulesPreview()}
      </aside>
    );
  };

  const moveStep = (i: number, dir: -1 | 1) => {
    const j = i + dir;
    if (j < 0 || j >= draft.nodes.length) return;
    const next = [...draft.nodes];
    [next[i], next[j]] = [next[j], next[i]];
    updateDraft({ nodes: next });
  };

  const removeStep = (i: number) => {
    if (draft.nodes.length <= 1) {
      pushToast("err", "A process needs at least one step.");
      return;
    }
    updateDraft({ nodes: draft.nodes.filter((_, idx) => idx !== i) });
  };

  const addStep = () => {
    const next = [...draft.nodes, { _key: `n${Date.now()}`, kind: "step", display_name: "New step", dispatch_kind: "human" }];
    updateDraft({ nodes: next });
  };

  return (
    <div className="wizard-container">
      <header className="wizard-header">
         <div>
          <div className="mc-hero-eyebrow"><Branch size={12} /> Process Creation Wizard</div>
          <h2 className="mc-hero-title">Build a new process</h2>
        </div>
        {renderStepNav()}
      </header>

      <div className="wizard-body">
        <div className="wizard-content">
          {draft.step === "Intake" && (
            <div className="wizard-panel">
              <h3 className="panel-h">What process do you want to build?</h3>
              <div className="field-group">
                  <label>Name (optional)</label>
                  <input
                    type="text"
                    value={draft.name}
                    onChange={e => updateDraft({ name: e.target.value })}
                    placeholder="e.g. Laptop Procurement"
                  />
              </div>
              <div className="field-group">
                  <label>Describe the process</label>
                  <textarea
                    value={draft.description}
                    onChange={e => updateDraft({ description: e.target.value })}
                    placeholder="When a store manager requests a new laptop, run a procurement approval..."
                    rows={4}
                  />
              </div>
              <button
                  className="btn btn-primary"
                  onClick={handleIntakeSubmit}
                  disabled={!draft.description || working || !canPublish}
              >
                {working ? "Saving..." : "Start drafting →"}
              </button>
              {!canPublish && <p className="warning-text">Switch to live mode + sign in to create processes.</p>}
            </div>
          )}

          {draft.step === "Analyze" && (
            <div className="wizard-panel">
              <h3 className="panel-h">What steps does it have?</h3>
              <p className="panel-sub">Reorder, rename, or pick who does each step. Order is preserved when we write to EA2.</p>
              <div className="node-list">
                {draft.nodes.map((n, i) => (
                  <div key={n._key} className="node-card">
                    <div className="node-header">
                      <span className="node-idx">{i + 1}</span>
                      <input
                        value={n.display_name}
                        onChange={e => {
                          const newNodes = [...draft.nodes];
                          newNodes[i].display_name = e.target.value;
                          updateDraft({ nodes: newNodes });
                        }}
                      />
                    </div>
                    <div className="node-meta">
                      <select
                        value={n.dispatch_kind}
                        onChange={e => {
                          const newNodes = [...draft.nodes];
                          newNodes[i].dispatch_kind = e.target.value;
                          updateDraft({ nodes: newNodes });
                        }}
                      >
                        <option value="human">Manual review</option>
                        <option value="agent">Assistant</option>
                        <option value="system">System</option>
                      </select>
                      <div className="node-controls">
                        <button className="icon-btn" onClick={() => moveStep(i, -1)} disabled={i === 0} title="Move up">↑</button>
                        <button className="icon-btn" onClick={() => moveStep(i, 1)} disabled={i === draft.nodes.length - 1} title="Move down">↓</button>
                        <button className="icon-btn" onClick={() => removeStep(i)} title="Remove"><Close size={12} /></button>
                      </div>
                    </div>
                  </div>
                ))}
                <button className="btn btn-secondary" onClick={addStep}>+ Add step</button>
              </div>
              <button className="btn btn-primary" onClick={handleStructureSave} disabled={working}>
                {working ? "Saving..." : "Confirm structure →"}
              </button>
            </div>
          )}

          {draft.step === "Generate" && (
            <div className="wizard-panel">
              <h3 className="panel-h">What information do you need to collect?</h3>
              <p className="panel-sub">These become the form every step asks for. You can add as many as you like.</p>
              <div className="field-list">
                  {draft.fields.map((f, i) => (
                      <div key={i} className="field-row">
                          <input
                              placeholder="e.g. requester name"
                              value={f.name}
                              onChange={e => {
                                  const newFields = [...draft.fields];
                                  newFields[i].name = e.target.value;
                                  updateDraft({ fields: newFields });
                              }}
                          />
                          <select
                              value={f.type}
                              onChange={e => {
                                  const newFields = [...draft.fields];
                                  newFields[i].type = e.target.value;
                                  updateDraft({ fields: newFields });
                              }}
                          >
                              <option value="string">Text</option>
                              <option value="number">Number</option>
                              <option value="boolean">Yes / No</option>
                          </select>
                          <button className="icon-btn" onClick={() => updateDraft({ fields: draft.fields.filter((_, idx) => idx !== i) })}><Close size={12} /></button>
                      </div>
                  ))}
                  <button className="btn btn-secondary" onClick={() => updateDraft({ fields: [...draft.fields, { name: "", type: "string" }] })}>+ Add field</button>
              </div>
              <button className="btn btn-primary" onClick={handleDataSave} disabled={working}>
                {working ? "Saving..." : "Confirm fields →"}
              </button>
            </div>
          )}

          {draft.step === "Validate" && (
             <div className="wizard-panel">
              <h3 className="panel-h">Anything special the process should check?</h3>
              <p className="panel-sub">Plain-English rules. We'll attach them as exception checks once published.</p>
               <div className="field-list">
                  {draft.rules.map((r, i) => (
                      <div key={i} className="field-row">
                          <input
                              placeholder="e.g. If cost is over 5000, require VP approval"
                              value={r}
                              onChange={e => {
                                  const newRules = [...draft.rules];
                                  newRules[i] = e.target.value;
                                  updateDraft({ rules: newRules });
                              }}
                              style={{ flex: 1 }}
                          />
                           <button className="icon-btn" onClick={() => updateDraft({ rules: draft.rules.filter((_, idx) => idx !== i) })}><Close size={12} /></button>
                      </div>
                  ))}
                   <button className="btn btn-secondary" onClick={() => updateDraft({ rules: [...draft.rules, ""] })}>+ Add rule</button>
              </div>
               <button className="btn btn-primary" onClick={handleRulesSave} disabled={working}>
                {working ? "Saving..." : "Review process →"}
              </button>
            </div>
          )}

          {draft.step === "Draft saved" && (
             <div className="wizard-panel">
              <h3 className="panel-h">Review &amp; publish</h3>
              <p className="panel-sub">Last look. Hit publish to write the definition + steps + form + version to EA2 in one atomic batch.</p>
              <div className="wizard-review">
                <div className="wizard-review-row">
                  <span className="wizard-review-label">Process</span>
                  <strong>{draft.name || "Untitled"}</strong>
                </div>
                {draft.description && (
                  <div className="wizard-review-row">
                    <span className="wizard-review-label">Purpose</span>
                    <span>{draft.description}</span>
                  </div>
                )}
                <div className="wizard-review-row">
                  <span className="wizard-review-label">Steps</span>
                  <span>{draft.nodes.length} ({draft.nodes.map((n) => n.display_name || "Untitled").join(" → ")})</span>
                </div>
                <div className="wizard-review-row">
                  <span className="wizard-review-label">Form fields</span>
                  <span>{draft.fields.filter((f) => f.name).length || "none"}</span>
                </div>
                <div className="wizard-review-row">
                  <span className="wizard-review-label">Rules</span>
                  <span>{draft.rules.filter((r) => r.trim()).length || "none"}</span>
                </div>
              </div>
              <div className="actions-row">
                  <button className="btn btn-secondary" onClick={() => updateDraft({ step: "Intake" })}>Back to edit</button>
                  <button className="btn btn-primary" onClick={handlePublish} disabled={working}>
                  {working ? "Publishing..." : "Publish to EA2"}
                  </button>
              </div>
            </div>
          )}

          {draft.step === "Publish" && (
               <div className="wizard-panel success-panel">
                  <div className="success-icon"><Check size={32} /></div>
                  <h3 className="panel-h">Process published</h3>
                  <p>Your process <strong>{draft.name || "Untitled"}</strong> is now active and ready to run.</p>
                  <div className="actions-row">
                       <button className="btn btn-secondary" onClick={() => { setDraft({ step: "Intake", name: "", description: "", nodes: [], edges: [], fields: [], rules: [] }); setPublishedKey(null); }}>Create another</button>
                       <button className="btn btn-primary" onClick={handleStartInstance} disabled={working}>
                          Start first instance
                      </button>
                  </div>
               </div>
          )}
        </div>

        {renderPreviewPane()}
      </div>
    </div>
  );
}
