// Live API call log. Every fetch the app makes shows up here in real time.
// Replaces the old guided-tour overlay.
import { useEffect, useRef, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { useApp } from "../state/store";
import { Close, Refresh, Layers, Pulse } from "./icons";

const METHOD_COLOR: Record<string, string> = {
  GET: "var(--bp-muted)",
  POST: "var(--bp-info)",
  PUT: "var(--bp-amber)",
  PATCH: "var(--bp-amber)",
  DELETE: "var(--bp-err)",
};

function statusClass(s: number): string {
  if (s === 0) return "err";
  if (s >= 500) return "err";
  if (s >= 400) return "warn";
  if (s >= 200) return "ok";
  return "info";
}

export default function Console() {
  const open = useApp((s) => s.consoleOpen);
  const setOpen = useApp((s) => s.setConsoleOpen);
  const log = useApp((s) => s.apiLog);
  const clear = useApp((s) => s.clearApiLog);
  const [expanded, setExpanded] = useState<number | null>(null);
  const [filter, setFilter] = useState<"all" | "writes" | "errors">("all");
  const tailRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    if (!open) return;
    tailRef.current?.scrollTo({ top: tailRef.current.scrollHeight, behavior: "smooth" });
  }, [log, open]);

  const filtered = log.filter((c) => {
    if (filter === "writes") return c.method !== "GET";
    if (filter === "errors") return c.status === 0 || c.status >= 400;
    return true;
  });

  return (
    <AnimatePresence>
      {open && (
        <motion.aside
          className="console"
          initial={{ x: 360, opacity: 0 }}
          animate={{ x: 0, opacity: 1 }}
          exit={{ x: 360, opacity: 0 }}
          transition={{ duration: 0.2 }}
          aria-label="API call console"
        >
          <header className="console-head">
            <Pulse size={13} />
            <span className="console-title">Live console</span>
            <span className="console-count mono">{log.length}</span>
            <div className="console-filters" role="tablist">
              <button className={`console-filter${filter === "all" ? " on" : ""}`} onClick={() => setFilter("all")}>all</button>
              <button className={`console-filter${filter === "writes" ? " on" : ""}`} onClick={() => setFilter("writes")}>writes</button>
              <button className={`console-filter${filter === "errors" ? " on" : ""}`} onClick={() => setFilter("errors")}>errors</button>
            </div>
            <button className="console-x" title="Clear" onClick={clear}><Refresh size={11} /></button>
            <button className="console-x" title="Close" onClick={() => setOpen(false)}><Close size={12} /></button>
          </header>
          <div className="console-body" ref={tailRef}>
            {filtered.length === 0 && (
              <div className="empty">No API calls yet. Flip to LIVE mode or perform an action.</div>
            )}
            {filtered.map((c) => {
              const isExpanded = expanded === c.id;
              const shortPath = c.path.replace(/^https?:\/\/[^/]+/, "");
              return (
                <div key={c.id} className={`call ${statusClass(c.status)}`}>
                  <button
                    className="call-head"
                    onClick={() => setExpanded(isExpanded ? null : c.id)}
                    title="Toggle body"
                  >
                    <span className="call-method mono" style={{ color: METHOD_COLOR[c.method] || "var(--text-2)" }}>{c.method}</span>
                    <span className="call-status mono">{c.status || "ERR"}</span>
                    <span className="call-path mono" title={c.path}>{shortPath}</span>
                    <span className="call-dur mono">{c.durationMs}ms</span>
                  </button>
                  {isExpanded && (
                    <div className="call-body">
                      {c.reqBody !== undefined && (
                        <>
                          <div className="call-label"><Layers size={10} /> request</div>
                          <pre className="call-json"><code>{JSON.stringify(c.reqBody, null, 2)}</code></pre>
                        </>
                      )}
                      {c.error && (
                        <>
                          <div className="call-label call-err"><Layers size={10} /> network error</div>
                          <pre className="call-json"><code>{c.error}</code></pre>
                        </>
                      )}
                      {c.resBody !== undefined && (
                        <>
                          <div className="call-label"><Layers size={10} /> response</div>
                          <pre className="call-json"><code>{typeof c.resBody === "string" ? c.resBody : JSON.stringify(c.resBody, null, 2)}</code></pre>
                        </>
                      )}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </motion.aside>
      )}
    </AnimatePresence>
  );
}
