// panels.jsx — visual file panels, commit graph, Octo mascot, badges

const { useState: usePState, useEffect: useEPanels, useRef: useRPanels } = React;

// ---------- File chip ----------
function FileChip({ name, content, status, conflict, onClick, small }) {
  // status: 'untracked' | 'modified' | 'staged-new' | 'staged-modified' | 'committed' | 'conflict'
  const palette = {
    "untracked":      { bg: "#FFE5E5", ink: "#8B0000", icon: "✱", label: "U" },
    "modified":       { bg: "#FFE9CC", ink: "#8B4513", icon: "●", label: "M" },
    "staged-new":     { bg: "#FFF3B0", ink: "#6B4E00", icon: "✚", label: "A" },
    "staged-modified":{ bg: "#FFF3B0", ink: "#6B4E00", icon: "▲", label: "M" },
    "committed":      { bg: "#C7F0BD", ink: "#1F4D17", icon: "✓", label: "✓" },
    "conflict":       { bg: "#FFB3B3", ink: "#660000", icon: "⚡", label: "!" },
  };
  const p = palette[status] || palette["untracked"];
  return (
    <div
      onClick={onClick}
      className="no-select"
      style={{
        display: "flex",
        alignItems: "center",
        gap: 8,
        padding: small ? "6px 10px" : "8px 12px",
        background: p.bg,
        border: "2px solid var(--ink)",
        borderRadius: 8,
        boxShadow: "var(--shadow-sm)",
        cursor: onClick ? "pointer" : "default",
        animation: status === "conflict" ? "shake 0.4s" : "pop-in 0.3s",
        fontFamily: "JetBrains Mono, monospace",
        fontSize: small ? 12 : 13,
        fontWeight: 600,
        color: p.ink,
        minWidth: 0,
      }}
    >
      <span style={{ fontSize: 14, lineHeight: 1 }}>{p.icon}</span>
      <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{name}</span>
    </div>
  );
}

// ---------- Working Directory panel ----------
function WorkingDirPanel({ state, onFileClick }) {
  const status = computeStatus(state);
  const files = Object.keys(state.workingDir);
  const headSha = state.branches[state.HEAD];
  const headTree = headSha ? state.commits[headSha].tree : {};

  const getStatus = (f) => {
    if (state.workingDir[f].conflict) return "conflict";
    if (status.untracked.includes(f)) return "untracked";
    if (status.modified.includes(f)) return "modified";
    return "committed";
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <PanelHeader
        icon="📂"
        title="Working Directory"
        sub="Files you're editing on your computer"
        accent="var(--local-accent)"
      />
      <div style={{
        display: "grid",
        gridTemplateColumns: "1fr 1fr",
        gap: 6,
        minHeight: 60,
        maxHeight: 180,
        overflowY: "auto",
        padding: 4,
      }}>
        {files.length === 0 && (
          <div style={{ gridColumn: "1 / -1", padding: 12, fontStyle: "italic", color: "#888", fontSize: 13, textAlign: "center" }}>
            (no files yet — try <code>echo "hi" {">"}  hello.txt</code>)
          </div>
        )}
        {files.map(f => (
          <FileChip
            key={f}
            name={f}
            status={getStatus(f)}
            content={state.workingDir[f].content}
            onClick={() => onFileClick && onFileClick(f)}
            small
          />
        ))}
      </div>
    </div>
  );
}

// ---------- Staging panel ----------
function StagingPanel({ state, onFileClick }) {
  const files = Object.keys(state.staging);
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <PanelHeader
        icon="📋"
        title="Staging Area"
        sub="Snapshot you're preparing to save"
        accent="var(--stage-accent)"
      />
      <div style={{
        display: "grid",
        gridTemplateColumns: "1fr 1fr",
        gap: 6,
        background: "var(--stage-bg)",
        borderRadius: 10,
        padding: 8,
        border: "2px dashed var(--stage-accent)",
        minHeight: 60,
        maxHeight: 180,
        overflowY: "auto",
      }}>
        {files.length === 0 && (
          <div style={{ gridColumn: "1 / -1", padding: 8, fontStyle: "italic", color: "#8a6d00", fontSize: 12, textAlign: "center" }}>
            empty — use <code>git add &lt;file&gt;</code> to stage changes
          </div>
        )}
        {files.map(f => (
          <FileChip key={f} name={f} status="staged-new" small onClick={() => onFileClick && onFileClick(f)} />
        ))}
      </div>
    </div>
  );
}

// ---------- Commit graph ----------
function CommitGraph({ state, side = "local", title }) {
  const source = side === "local" ? state : { commits: state.remote.commits, branches: state.remote.branches };
  const commits = source.commits;
  const branches = source.branches || {};

  // Build linear list ordered by time (newest first), but with branch lanes
  const sortedCommits = Object.values(commits).sort((a, b) => b.time - a.time);
  if (sortedCommits.length === 0) {
    return (
      <div style={{ padding: 14, textAlign: "center", color: "#888", fontStyle: "italic", fontSize: 12 }}>
        No commits yet.
      </div>
    );
  }

  // Assign lane per branch
  const branchList = Object.keys(branches);
  const lane = {};
  branchList.forEach((b, i) => { lane[b] = i; });
  const laneColor = ["#FF7A45", "#6366F1", "#FFD93D", "#FF6B9D", "#2E7D32"];

  // Find which branch tips at this commit
  const tipsBy = {};
  Object.entries(branches).forEach(([b, s]) => {
    if (s) (tipsBy[s] = tipsBy[s] || []).push(b);
  });

  const headBranch = side === "local" ? state.HEAD : null;

  return (
    <div style={{
      maxHeight: 280,
      overflowY: "auto",
      padding: "8px 6px",
    }}>
      <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
        {sortedCommits.map((c, i) => {
          const color = laneColor[(lane[c.branch] || 0) % laneColor.length];
          const isHead = side === "local" && state.branches[headBranch] === c.sha;
          return (
            <div key={c.sha} style={{ display: "flex", alignItems: "center", gap: 8, position: "relative" }}>
              {/* Lane line */}
              <div style={{
                width: 24,
                position: "relative",
                height: 32,
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
              }}>
                {i < sortedCommits.length - 1 && (
                  <div style={{
                    position: "absolute",
                    top: 16, bottom: -4,
                    left: "50%",
                    width: 2,
                    background: color,
                  }} />
                )}
                <div style={{
                  width: 14, height: 14,
                  borderRadius: "50%",
                  background: color,
                  border: "2px solid var(--ink)",
                  zIndex: 1,
                  animation: i === 0 ? "pop-in 0.4s" : "none",
                  boxShadow: c.parent2 ? `0 0 0 3px ${color}55` : "none",
                }} />
              </div>
              <div style={{
                flex: 1, minWidth: 0,
                background: isHead ? "var(--joy)" : "white",
                border: "2px solid var(--ink)",
                borderRadius: 8,
                padding: "4px 8px",
                fontSize: 11,
                fontFamily: "JetBrains Mono, monospace",
                display: "flex",
                gap: 6,
                alignItems: "center",
                overflow: "hidden",
              }}>
                <span style={{ color, fontWeight: 700, flexShrink: 0 }}>{c.sha}</span>
                <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flex: 1 }}>{c.msg}</span>
                {c.author === "Riley" && (
                  <span style={{ background: "#FFB3D9", border: "1.5px solid var(--ink)", borderRadius: 6, padding: "1px 5px", fontSize: 10, fontFamily: "Space Grotesk", flexShrink: 0 }}>R</span>
                )}
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 2, flexShrink: 0 }}>
                {(tipsBy[c.sha] || []).map(b => (
                  <div key={b} className="chip" style={{
                    background: b === headBranch ? "var(--joy)" : "white",
                    fontSize: 10,
                    padding: "1px 6px",
                  }}>
                    {b === headBranch ? "★ " : ""}{b}
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ---------- Header for sub-panels ----------
function PanelHeader({ icon, title, sub, accent }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      <div style={{
        width: 32, height: 32,
        background: accent,
        border: "2px solid var(--ink)",
        borderRadius: 8,
        display: "flex", alignItems: "center", justifyContent: "center",
        fontSize: 18,
        boxShadow: "var(--shadow-sm)",
      }}>{icon}</div>
      <div>
        <div style={{ fontWeight: 700, fontSize: 14 }}>{title}</div>
        <div style={{ fontSize: 11, opacity: 0.7 }}>{sub}</div>
      </div>
    </div>
  );
}

// ---------- Local Machine column ----------
function LocalColumn({ state, onFileClick }) {
  return (
    <div className="panel panel-lg" style={{
      background: "linear-gradient(180deg, var(--local-bg-soft) 0%, var(--local-bg) 100%)",
      padding: 16,
      display: "flex",
      flexDirection: "column",
      gap: 14,
      overflow: "hidden",
      minHeight: 0,
      width: "100%",
      height: "100%",
      flex: 1,
    }}>
      <ColumnHeader
        title="YOUR COMPUTER"
        sub="local machine"
        emoji="💻"
        accent="var(--local-accent)"
        ink="var(--local-ink)"
      />
      <WorkingDirPanel state={state} onFileClick={onFileClick} />
      <StagingPanel state={state} onFileClick={onFileClick} />
      <div style={{ display: "flex", flexDirection: "column", gap: 8, flex: 1, minHeight: 0 }}>
        <PanelHeader icon="🌳" title="Local Commits" sub={`current branch: ${state.HEAD}`} accent="var(--commit-accent)" />
        <div style={{
          background: "var(--commit-bg)",
          border: "2px solid var(--ink)",
          borderRadius: 10,
          flex: 1,
          minHeight: 100,
          overflow: "hidden",
        }}>
          <CommitGraph state={state} side="local" />
        </div>
      </div>
    </div>
  );
}

// ---------- Remote / GitHub column ----------
function RemoteColumn({ state }) {
  if (!state.remote.exists) {
    return (
      <div className="panel panel-lg" style={{
        background: "linear-gradient(180deg, var(--remote-bg-soft) 0%, var(--remote-bg) 100%)",
        padding: 16,
        display: "flex", flexDirection: "column",
        alignItems: "center", justifyContent: "center",
        gap: 16,
        textAlign: "center",
        minHeight: 0,
        width: "100%",
        height: "100%",
        flex: 1,
      }}>
        <ColumnHeader
          title="GITHUB.COM"
          sub="remote"
          emoji="☁️"
          accent="var(--remote-accent)"
          ink="var(--remote-ink)"
        />
        <div style={{
          padding: 24,
          border: "3px dashed var(--remote-accent)",
          borderRadius: 14,
          color: "var(--remote-ink)",
          maxWidth: 280,
        }}>
          <div style={{ fontSize: 40, marginBottom: 8 }}>📡</div>
          <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 6 }}>No remote yet</div>
          <div style={{ fontSize: 12, opacity: 0.8 }}>
            Connect to GitHub with:<br/>
            <code className="mono" style={{ background: "white", padding: "2px 6px", borderRadius: 4, marginTop: 6, display: "inline-block" }}>
              git remote add origin &lt;url&gt;
            </code>
          </div>
        </div>
      </div>
    );
  }

  const prs = state.remote.pullRequests;

  return (
    <div className="panel panel-lg" style={{
      background: "linear-gradient(180deg, var(--remote-bg-soft) 0%, var(--remote-bg) 100%)",
      padding: 16,
      display: "flex",
      flexDirection: "column",
      gap: 14,
      overflow: "hidden",
      minHeight: 0,
      width: "100%",
      height: "100%",
      flex: 1,
    }}>
      <ColumnHeader
        title="GITHUB.COM"
        sub={state.remote.url?.replace(/^https?:\/\//, "") || "origin"}
        emoji="☁️"
        accent="var(--remote-accent)"
        ink="var(--remote-ink)"
      />

      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <PanelHeader icon="🌿" title="Remote Branches" sub="what's on origin" accent="var(--remote-accent)" />
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
          {Object.entries(state.remote.branches).length === 0 && (
            <div style={{ fontStyle: "italic", color: "#888", fontSize: 12 }}>nothing pushed yet</div>
          )}
          {Object.entries(state.remote.branches).map(([b, s]) => (
            <div key={b} className="chip" style={{ background: "white" }}>
              <span style={{ color: "var(--remote-accent-deep)" }}>{b}</span>
              <span style={{ opacity: 0.5 }}>@{s?.slice(0, 7)}</span>
            </div>
          ))}
        </div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <PanelHeader icon="🔀" title="Pull Requests" sub="discussions about changes" accent="var(--octo)" />
        <div style={{ display: "flex", flexDirection: "column", gap: 6, maxHeight: 100, overflowY: "auto" }}>
          {prs.length === 0 && (
            <div style={{ fontStyle: "italic", color: "#888", fontSize: 12 }}>no PRs yet</div>
          )}
          {prs.map(pr => (
            <div key={pr.id} className="pop-in" style={{
              background: pr.status === "merged" ? "#C7B3FF" : "white",
              border: "2px solid var(--ink)",
              borderRadius: 8,
              padding: "6px 10px",
              fontSize: 12,
              display: "flex", alignItems: "center", gap: 8,
            }}>
              <span style={{ fontWeight: 700, color: "var(--remote-accent-deep)" }}>#{pr.id}</span>
              <span style={{ flex: 1, fontSize: 11 }}>{pr.title}</span>
              <span className="chip" style={{
                background: pr.status === "open" ? "#B5E48C" : "#C7B3FF",
                fontSize: 10, padding: "1px 6px",
              }}>{pr.status}</span>
            </div>
          ))}
        </div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 8, flex: 1, minHeight: 0 }}>
        <PanelHeader icon="🌳" title="Remote Commits" sub="history on origin" accent="var(--remote-accent)" />
        <div style={{
          background: "white",
          border: "2px solid var(--ink)",
          borderRadius: 10,
          flex: 1,
          minHeight: 100,
          overflow: "hidden",
        }}>
          <CommitGraph state={state} side="remote" />
        </div>
      </div>
    </div>
  );
}

function ColumnHeader({ title, sub, emoji, accent, ink }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      <div style={{
        width: 44, height: 44,
        background: accent,
        border: "3px solid var(--ink)",
        borderRadius: 12,
        display: "flex", alignItems: "center", justifyContent: "center",
        fontSize: 24,
        boxShadow: "var(--shadow-sm)",
      }}>{emoji}</div>
      <div>
        <div style={{
          fontWeight: 700,
          fontSize: 18,
          letterSpacing: "0.02em",
          color: ink,
          fontFamily: "Space Grotesk",
        }}>{title}</div>
        <div className="mono" style={{ fontSize: 11, opacity: 0.7, color: ink }}>{sub}</div>
      </div>
    </div>
  );
}

// ---------- Octo mascot ----------
function Octo({ mood = "happy", size = 80 }) {
  // mood: 'happy' | 'thinking' | 'celebrate' | 'error' | 'wave'
  const eyes = mood === "celebrate" ? "^^" : mood === "thinking" ? "·_·" : mood === "error" ? "x_x" : "•‿•";
  const tilt = mood === "wave" ? -6 : 0;
  return (
    <div style={{
      width: size, height: size,
      position: "relative",
      animation: mood === "wave" ? "wiggle 1.2s ease-in-out infinite" : "none",
      transform: `rotate(${tilt}deg)`,
      flexShrink: 0,
    }}>
      <svg viewBox="0 0 100 100" width={size} height={size}>
        {/* tentacles */}
        <g stroke="var(--ink)" strokeWidth="2.5" fill="var(--octo)" strokeLinejoin="round">
          <path d="M 20 70 Q 10 80 14 92 Q 22 96 24 84 Z" />
          <path d="M 35 75 Q 30 90 38 95 Q 44 92 42 80 Z" />
          <path d="M 50 78 Q 50 92 56 94 Q 60 88 56 80 Z" />
          <path d="M 65 75 Q 70 90 78 92 Q 80 84 72 78 Z" />
          <path d="M 80 70 Q 92 78 90 90 Q 82 94 76 84 Z" />
        </g>
        {/* head */}
        <ellipse cx="50" cy="45" rx="32" ry="28" fill="var(--octo)" stroke="var(--ink)" strokeWidth="3" />
        {/* highlight */}
        <ellipse cx="40" cy="32" rx="9" ry="6" fill="white" opacity="0.5" />
        {/* eyes */}
        <text x="50" y="50" fontSize="14" fontFamily="JetBrains Mono" textAnchor="middle" fill="var(--ink)" fontWeight="700">{eyes}</text>
        {/* mouth */}
        {mood === "celebrate" && <path d="M 44 58 Q 50 64 56 58" stroke="var(--ink)" strokeWidth="2" fill="none" strokeLinecap="round" />}
        {mood === "thinking" && <circle cx="50" cy="60" r="2" fill="var(--ink)" />}
        {mood === "error" && <path d="M 44 60 Q 50 56 56 60" stroke="var(--ink)" strokeWidth="2" fill="none" strokeLinecap="round" />}
        {mood === "happy" && <path d="M 45 58 Q 50 62 55 58" stroke="var(--ink)" strokeWidth="2" fill="none" strokeLinecap="round" />}
        {mood === "wave" && <path d="M 45 58 Q 50 62 55 58" stroke="var(--ink)" strokeWidth="2" fill="none" strokeLinecap="round" />}
      </svg>
    </div>
  );
}

// ---------- File viewer modal ----------
function FileViewer({ filename, content, onClose, conflict }) {
  if (!filename) return null;
  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0,
      background: "rgba(26,20,16,0.55)",
      zIndex: 500,
      display: "flex", alignItems: "center", justifyContent: "center",
      padding: 24,
    }}>
      <div onClick={e => e.stopPropagation()} className="panel pop-in" style={{
        background: "var(--paper)",
        padding: 18,
        maxWidth: 600, width: "100%",
        maxHeight: "80vh",
        display: "flex", flexDirection: "column", gap: 12,
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <div className="chip mono" style={{ background: conflict ? "#FFB3B3" : "var(--joy)" }}>{filename}</div>
          {conflict && <div className="chip" style={{ background: "var(--conflict)", color: "white" }}>CONFLICT</div>}
          <div style={{ flex: 1 }} />
          <button className="btn" onClick={onClose}>close</button>
        </div>
        <pre className="mono" style={{
          background: conflict ? "#FFF0F0" : "white",
          border: "2px solid var(--ink)",
          borderRadius: 8,
          padding: 12,
          margin: 0,
          fontSize: 13,
          overflow: "auto",
          whiteSpace: "pre-wrap",
        }}>{content || "(empty file)"}</pre>
      </div>
    </div>
  );
}

// ---------- Badge popup ----------
function BadgePopup({ badge, onDismiss }) {
  useEPanels(() => {
    const t = setTimeout(onDismiss, 3200);
    return () => clearTimeout(t);
  }, [badge, onDismiss]);
  if (!badge) return null;
  return (
    <div style={{
      position: "fixed",
      top: 24,
      left: "50%",
      transform: "translateX(-50%)",
      zIndex: 600,
      animation: "pop-in 0.4s",
      pointerEvents: "none",
    }}>
      <div className="panel" style={{
        background: "var(--joy)",
        padding: "12px 22px",
        display: "flex", alignItems: "center", gap: 12,
        boxShadow: "6px 6px 0 var(--ink)",
      }}>
        <div style={{ fontSize: 32 }}>🏆</div>
        <div>
          <div style={{ fontSize: 11, opacity: 0.7, fontWeight: 600 }}>BADGE UNLOCKED</div>
          <div style={{ fontSize: 18, fontWeight: 700 }}>{badge.name}</div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  WorkingDirPanel, StagingPanel, CommitGraph,
  LocalColumn, RemoteColumn, Octo,
  FileViewer, BadgePopup, FileChip, PanelHeader,
});
