/* Reusable primitives + iconography. */

// Tiny icon set — line-style, 14px default. No external icons.
const Icon = ({ name, size = 14, stroke = 1.5 }) => {
  const props = {
    width: size, height: size, viewBox: "0 0 24 24",
    fill: "none", stroke: "currentColor", strokeWidth: stroke,
    strokeLinecap: "round", strokeLinejoin: "round",
  };
  switch (name) {
    case "play": return <svg {...props}><path d="M6 4l14 8-14 8z" fill="currentColor" stroke="none" /></svg>;
    case "pause": return <svg {...props}><rect x="6" y="4" width="4" height="16" fill="currentColor" stroke="none"/><rect x="14" y="4" width="4" height="16" fill="currentColor" stroke="none"/></svg>;
    case "check": return <svg {...props}><path d="M4 12l5 5L20 6"/></svg>;
    case "x": return <svg {...props}><path d="M5 5l14 14M19 5L5 19"/></svg>;
    case "chev-r": return <svg {...props}><path d="M9 6l6 6-6 6"/></svg>;
    case "chev-l": return <svg {...props}><path d="M15 6l-6 6 6 6"/></svg>;
    case "chev-d": return <svg {...props}><path d="M6 9l6 6 6-6"/></svg>;
    case "link": return <svg {...props}><path d="M10 14a4 4 0 0 1 0-6l3-3a4 4 0 0 1 6 6l-1.5 1.5"/><path d="M14 10a4 4 0 0 1 0 6l-3 3a4 4 0 0 1-6-6l1.5-1.5"/></svg>;
    case "plus": return <svg {...props}><path d="M12 5v14M5 12h14"/></svg>;
    case "regen": return <svg {...props}><path d="M21 12a9 9 0 1 1-3-6.7M21 4v5h-5"/></svg>;
    case "warn": return <svg {...props}><path d="M12 3l10 18H2zM12 10v5M12 18v.5"/></svg>;
    case "lock": return <svg {...props}><rect x="5" y="11" width="14" height="9" rx="1.5"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg>;
    case "eye": return <svg {...props}><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg>;
    case "eye-off": return <svg {...props}><path d="M3 3l18 18M10.6 6.1A9.7 9.7 0 0 1 12 6c6 0 10 6 10 6a17 17 0 0 1-3.2 3.7M6.7 7.7A18 18 0 0 0 2 12s4 6 10 6a9 9 0 0 0 4-1"/><path d="M9.5 9.5a3 3 0 0 0 4.2 4.2"/></svg>;
    case "film": return <svg {...props}><rect x="3" y="4" width="18" height="16" rx="1.5"/><path d="M3 9h3M3 15h3M18 9h3M18 15h3M9 4v16M15 4v16"/></svg>;
    case "wave": return <svg {...props}><path d="M2 12c2-6 4-6 6 0s4 8 6 0 4-4 6 0 4 0 4 0"/></svg>;
    case "render": return <svg {...props}><path d="M5 4h14v16H5z"/><path d="M9 9h6v6H9z" fill="currentColor" stroke="none"/></svg>;
    case "stale": return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>;
    case "dot": return <svg {...props}><circle cx="12" cy="12" r="5" fill="currentColor" stroke="none"/></svg>;
    case "dollar": return <svg {...props}><path d="M12 3v18M16 7H10a3 3 0 0 0 0 6h4a3 3 0 0 1 0 6H8"/></svg>;
    case "search": return <svg {...props}><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></svg>;
    case "settings": return <svg {...props}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 0 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 0 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>;
    case "sparkle": return <svg {...props}><path d="M12 3v6M12 15v6M3 12h6M15 12h6"/></svg>;
    case "clap": return <svg {...props}><rect x="3" y="9" width="18" height="11" rx="1"/><path d="M3 9l3-5h4l-2 5M10 9l2-5h4l-2 5M17 9l2-5h2v5"/></svg>;
    default: return null;
  }
};

// Tension curve sparkline (svg path)
const TensionCurve = ({ points = [], height = 28, width = 120, color = "var(--accent)" }) => {
  if (!points.length) return null;
  const max = 9;
  const stepX = width / (points.length - 1);
  const path = points.map((p, i) => {
    const x = i * stepX;
    const y = height - (p / max) * (height - 4) - 2;
    return `${i === 0 ? "M" : "L"} ${x.toFixed(1)} ${y.toFixed(1)}`;
  }).join(" ");
  // area
  const area = path + ` L ${width} ${height} L 0 ${height} Z`;
  return (
    <svg width={width} height={height} className="viz" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none">
      <path d={area} fill={color} opacity="0.12" />
      <path d={path} fill="none" stroke={color} strokeWidth="1.5" />
      {points.map((p, i) => (
        <circle key={i} cx={i * stepX} cy={height - (p / max) * (height - 4) - 2} r="1.5" fill={color} />
      ))}
    </svg>
  );
};

// Iris/aperture motif for threat visibility
const Aperture = ({ value = "shadow", size = 36 }) => {
  // map visibility 0..4
  const map = { unseen: 0, heard: 1, shadow: 2, partial: 3, full: 4 };
  const v = map[value] ?? 0;
  const ringR = size / 2 - 1;
  const blades = 6;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={size/2} cy={size/2} r={ringR} fill="none" stroke="var(--line-strong)" strokeWidth="1"/>
      {Array.from({ length: blades }).map((_, i) => {
        const a = (i / blades) * Math.PI * 2;
        const x = size/2 + Math.cos(a) * ringR * 0.6;
        const y = size/2 + Math.sin(a) * ringR * 0.6;
        return <line key={i} x1={size/2} y1={size/2} x2={x} y2={y} stroke="var(--line-strong)" strokeWidth="1" />;
      })}
      <circle cx={size/2} cy={size/2} r={2 + v * 2.5} fill="var(--accent)" opacity="0.9" />
    </svg>
  );
};

// Filmstrip nav
const Filmstrip = ({ stages, active, onJump }) => (
  <nav className="filmstrip">
    {stages.map((s, i) => (
      <button
        key={s.key}
        className={`frame ${s.key === active ? "active" : ""} ${s.status === "warn" ? "warn" : ""}`}
        onClick={() => onJump(s.key)}
      >
        <div className="num">{s.num}</div>
        <div className="label">{s.label}</div>
        <div className="stat">{s.stat}</div>
      </button>
    ))}
  </nav>
);

// The Maton — Cobalt Lab
const MatonMark = ({ size = 20 }) => (
  <svg width={size} height={size * (200/220)} viewBox="-110 -100 220 200" aria-label="Cinematon">
    <rect x="-78" y="-50" width="156" height="100" rx="6" fill="none" stroke="#e9e8e3" strokeWidth="3"/>
    <g fill="#e9e8e3">
      <rect x="-66" y="-60" width="10" height="6" rx="1"/><rect x="-42" y="-60" width="10" height="6" rx="1"/>
      <rect x="-18" y="-60" width="10" height="6" rx="1"/><rect x="6" y="-60" width="10" height="6" rx="1"/>
      <rect x="30" y="-60" width="10" height="6" rx="1"/><rect x="54" y="-60" width="10" height="6" rx="1"/>
      <rect x="-66" y="54" width="10" height="6" rx="1"/><rect x="-42" y="54" width="10" height="6" rx="1"/>
      <rect x="-18" y="54" width="10" height="6" rx="1"/><rect x="6" y="54" width="10" height="6" rx="1"/>
      <rect x="30" y="54" width="10" height="6" rx="1"/><rect x="54" y="54" width="10" height="6" rx="1"/>
    </g>
    <line x1="-78" y1="0" x2="78" y2="0" stroke="#5e9bff" strokeWidth="3"/>
    <circle cx="14" cy="0" r="11" fill="#5e9bff"/>
    <circle cx="-72" cy="0" r="3.5" fill="#e9e8e3"/>
    <circle cx="72" cy="0" r="3.5" fill="#e9e8e3"/>
  </svg>
);

// Title bar — supports project rename (click title), project switcher (click "Projects"),
// and "+ New Project" trigger.
const Titlebar = ({ project, runtime, onCommandPalette, onNewProject, onSwitchProject, onRenameProject, onDeleteProject, projects, isLive }) => {
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState(project.title);
  const [showSwitcher, setShowSwitcher] = React.useState(false);
  const [apiReachable, setApiReachable] = React.useState(Boolean(window.CinematonAPI?.live));

  React.useEffect(() => { setDraft(project.title); }, [project.title]);
  React.useEffect(() => {
    const onLive = () => setApiReachable(true);
    window.addEventListener('cinematon:live', onLive);
    return () => window.removeEventListener('cinematon:live', onLive);
  }, []);

  const commit = () => {
    setEditing(false);
    if (draft && draft !== project.title && onRenameProject) onRenameProject(draft);
  };

  return (
    <header className="titlebar">
      <div className="traffic"><span/><span/><span/></div>
      <div className="brand">
        <MatonMark size={22}/>
        <span className="brand-name">Cinematon<span className="brand-sub">Studio</span></span>
      </div>
      <div className="crumbs">
        <span className="sep">/</span>
        <button
          className="tb-link"
          onClick={() => onSwitchProject && setShowSwitcher((x) => !x)}
          title="Switch project"
        >
          Projects
        </button>
        <span className="sep">/</span>
        {editing && isLive ? (
          <input
            className="tb-rename"
            autoFocus
            value={draft}
            onChange={(e) => setDraft(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') commit();
              if (e.key === 'Escape') { setDraft(project.title); setEditing(false); }
            }}
            onBlur={commit}
          />
        ) : (
          <span
            className={`now ${isLive ? 'tb-rename-target' : ''}`}
            onClick={() => isLive && onRenameProject && setEditing(true)}
            title={isLive ? 'Click to rename' : ''}
          >
            {project.title}
          </span>
        )}
        {showSwitcher && projects && (
          <ProjectSwitcher
            current={project.id}
            projects={projects}
            onClose={() => setShowSwitcher(false)}
            onSwitch={(id) => { setShowSwitcher(false); onSwitchProject(id); }}
            onDelete={onDeleteProject}
          />
        )}
      </div>
      <div className="right">
        {apiReachable && (
          <span className="pill live" title={isLive ? 'Live data' : 'API reachable — click + New Project to begin'}>
            {isLive ? 'LIVE' : 'API READY'}
          </span>
        )}
        <span className="pill">canon v{project.canon_version}</span>
        <span className="pill">{project.genre}</span>
        <span className="pill">HIGGSFIELD</span>
        {onNewProject && (
          <button className="btn primary" onClick={onNewProject} title="Start a new project">
            + New Project
          </button>
        )}
        <button className="btn ghost" onClick={onCommandPalette}><Icon name="search"/> Command <span className="kbd">⌘K</span></button>
      </div>
    </header>
  );
};

// Lightweight popover dropdown for project switching.
const ProjectSwitcher = ({ current, projects, onClose, onSwitch, onDelete }) => {
  React.useEffect(() => {
    const onDocClick = (e) => {
      if (!e.target.closest('.tb-switcher') && !e.target.closest('.tb-link')) onClose();
    };
    document.addEventListener('mousedown', onDocClick);
    return () => document.removeEventListener('mousedown', onDocClick);
  }, [onClose]);

  return (
    <div className="tb-switcher">
      <div className="tb-switcher-head">SWITCH PROJECT</div>
      {projects.length === 0 && <div className="tb-switcher-empty">No projects yet.</div>}
      {projects.map((p) => (
        <div key={p.id} className={`tb-switcher-row ${p.id === current ? 'current' : ''}`}>
          <button className="tb-switcher-pick" onClick={() => onSwitch(p.id)}>
            <span className="tb-switcher-title">{p.title}</span>
            <span className="tb-switcher-meta">{p.id.slice(0, 14)}</span>
          </button>
          {onDelete && (
            <button
              className="tb-switcher-del"
              title="Delete project"
              onClick={(e) => { e.stopPropagation(); onDelete(p.id); }}
            >
              ⌫
            </button>
          )}
        </div>
      ))}
    </div>
  );
};

// Status bar
const Statusbar = ({ project, validation, density, setDensity }) => {
  const warns = validation.filter(v => v.kind === "warn").length;
  const oks = validation.filter(v => v.kind === "ok").length;
  return (
    <footer className="statusbar">
      <div className="seg ok"><span className="dot"/>SCHEMA · {oks} pass</div>
      <div className={`seg ${warns ? "warn" : "ok"}`}><span className="dot"/>QA · {warns} warning{warns!==1?"s":""}</div>
      <div className="seg"><span className="dot"/>CANON v{project.canon_version} · LOCKED</div>
      <div className="seg"><span className="dot"/>EST RUNTIME {fmtTime(project.runtime_estimate)} / {fmtTime(project.runtime_target)}</div>
      <div className="right">
        <button className="seg" onClick={() => setDensity(density === "compact" ? "comfortable" : "compact")}>
          DENSITY · {density.toUpperCase()}
        </button>
        <div className="seg">SAVED · 12s AGO</div>
      </div>
    </footer>
  );
};

const fmtTime = (s) => `${String(Math.floor(s/60)).padStart(2,"0")}:${String(Math.floor(s%60)).padStart(2,"0")}`;

const PageHeader = ({ title, sub, children }) => (
  <div className="page-header">
    <div className="col" style={{ gap: 4 }}>
      <div className="title">{title}</div>
      <div className="sub">{sub}</div>
    </div>
    <div className="actions">{children}</div>
  </div>
);

Object.assign(window, { Icon, TensionCurve, Aperture, Filmstrip, Titlebar, ProjectSwitcher, Statusbar, PageHeader, MatonMark, fmtTime });
