/* eslint-disable */
// GuidelinesEditor — markdown editor for agent config files
// Props (TS): { files?: GuidelineFile[]; onSave?(file): void }
// GuidelineFile = { name: string; content: string; updatedAt: string }

const DEFAULT_FILES = [
  { name: "AGENTS.md", content:
`# Lazytrade — AI Agent Guidelines

This document defines the operating principles, responsibilities, and best practices for AI agents working within the Lazytrade platform.

## 1. Core Principles

- **Accuracy First**: Always prioritize accuracy and reliability over speed.
- **Risk Awareness**: Understand and respect market risks in all actions and recommendations.
- **Transparency**: Provide clear reasoning and concise explanations.
- **User Alignment**: Align with the user's goals, risk tolerance, and preferences.
- **Compliance**: Follow all compliance and regulatory guidelines.

## 2. Agent Responsibilities

1. **Market Analysis**
   - Monitor market data, news, and events.
   - Identify trends, patterns, and opportunities.
   - Communicate insights with clear rationale.

2. **Trade Assistance**
   - Suggest trade ideas based on strategy and risk parameters.
   - Validate inputs and constraints before execution.
   - Never execute trades without explicit user confirmation.

3. **Risk Management**
   - Continuously monitor positions and exposure.
   - Alert users to potential risks and limit breaches.
   - Recommend risk mitigation actions.

## 3. Best Practices

> Be concise, clear, and actionable. Use tables, charts, and code blocks where helpful.
> Confirm understanding of user requests before acting on them.
`, updatedAt: "May 24, 10:31 AM", dirty: false },
  { name: "trading-guidelines.md", content:
`# Trading Guidelines

## Position sizing
- Max 5% equity per position
- Aggregate net exposure: 60% long / 40% short ceiling
- Single-asset concentration ≤ 15%

## Stop-loss policy
- Always set a stop within 1.5x daily ATR
- Trailing stops on positions held > 24h
- Hard liquidation guardrail at 8% drawdown

## Approved venues
1. Binance (spot + perp)
2. Coinbase Advanced
3. Bybit (perp only)
`, updatedAt: "May 22, 4:08 PM", dirty: false },
  { name: "email-guidelines.md", content:
`# Email Guidelines

When summarizing weekly P&L by email:
- Subject line: \`[Lazytrade] Weekly Recap — <Mon DD>\`
- Open with one-sentence headline (net P&L, win rate)
- Three-bullet "what moved the book"
- Top 3 trades by absolute P&L
- Forward-look paragraph (≤ 60 words)

Tone: factual, no hype. Never include unrealised P&L of currently-open positions.
`, updatedAt: "May 21, 9:00 AM", dirty: false },
  { name: "monitoring-guidelines.md", content:
`# Monitoring Guidelines

Pi's monitoring loop checks the book every 30s.

## Alert thresholds
- Latency to exchange > 800ms → \`warn\`
- Latency to exchange > 1500ms → \`critical\`
- Heartbeat missed > 3 cycles → page on-call
- Drawdown > 4% on a position → notify user
- Drawdown > 6% on the book → halt new orders

## Recovery
- Auto-reconnect WS on disconnect (3 attempts, 2s backoff)
- After 3 failures, escalate to standby gateway
`, updatedAt: "May 20, 2:14 PM", dirty: false },
  { name: "llm-guidelines.md", content:
`# LLM Guidelines

## Routing
- Default to DeepSeek for chat completions
- Switch to Moonshot for >32k context summarisation
- xAI/Grok for live-news interpretation
- OpenRouter as fallback when any primary < $1 balance

## Prompting
- Always include the current UTC timestamp
- Pass the active strategy ID, never the full strategy doc
- Strip PII from logs before persisting

## Budget
- Soft cap: $130/mo total
- Hard cap per provider as configured in API Balance Monitor
`, updatedAt: "May 19, 11:42 AM", dirty: false },
];

/* very small markdown renderer */
function renderMd(src) {
  const lines = src.split("\n");
  const out = [];
  let inCode = false, codeBuf = [];
  let listBuf = null;

  const flushList = () => {
    if (listBuf) {
      out.push({ kind: listBuf.kind, items: listBuf.items });
      listBuf = null;
    }
  };

  const inline = (s) => {
    const parts = [];
    const re = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/g;
    let last = 0, m;
    while ((m = re.exec(s)) !== null) {
      if (m.index > last) parts.push(s.slice(last, m.index));
      parts.push(m[0]);
      last = m.index + m[0].length;
    }
    if (last < s.length) parts.push(s.slice(last));
    return parts.map((p, i) => {
      if (p.startsWith("**") && p.endsWith("**"))
        return <strong key={i} style={{ color: "var(--text-1)" }}>{p.slice(2, -2)}</strong>;
      if (p.startsWith("`") && p.endsWith("`"))
        return <code key={i} className="mono" style={{
          background: "var(--bg-2)", color: "var(--accent)",
          padding: "1px 6px", borderRadius: 4, fontSize: 12,
          border: "1px solid var(--border-s)"
        }}>{p.slice(1, -1)}</code>;
      return <span key={i}>{p}</span>;
    });
  };

  lines.forEach((raw) => {
    if (raw.trim().startsWith("```")) {
      if (inCode) { out.push({ kind: "code", body: codeBuf.join("\n") }); codeBuf = []; inCode = false; }
      else { flushList(); inCode = true; }
      return;
    }
    if (inCode) { codeBuf.push(raw); return; }

    if (/^#\s/.test(raw))       { flushList(); out.push({ kind: "h1", text: raw.slice(2) }); return; }
    if (/^##\s/.test(raw))      { flushList(); out.push({ kind: "h2", text: raw.slice(3) }); return; }
    if (/^###\s/.test(raw))     { flushList(); out.push({ kind: "h3", text: raw.slice(4) }); return; }
    if (/^>\s/.test(raw))       { flushList(); out.push({ kind: "quote", text: raw.slice(2) }); return; }
    const ul = raw.match(/^[\-\*]\s+(.*)/);
    const ol = raw.match(/^(\d+)\.\s+(.*)/);
    if (ul) {
      if (!listBuf || listBuf.kind !== "ul") { flushList(); listBuf = { kind: "ul", items: [] }; }
      listBuf.items.push(ul[1]);
      return;
    }
    if (ol) {
      if (!listBuf || listBuf.kind !== "ol") { flushList(); listBuf = { kind: "ol", items: [] }; }
      listBuf.items.push(ol[2]);
      return;
    }
    flushList();
    if (raw.trim()) out.push({ kind: "p", text: raw });
    else out.push({ kind: "spacer" });
  });
  flushList();
  if (inCode && codeBuf.length) out.push({ kind: "code", body: codeBuf.join("\n") });

  return out.map((b, i) => {
    switch (b.kind) {
      case "h1": return <h1 key={i} style={{ fontSize: 24, fontWeight: 700, margin: "0 0 8px", letterSpacing: "-0.02em" }}>{inline(b.text)}</h1>;
      case "h2": return <h2 key={i} style={{ fontSize: 17, fontWeight: 700, margin: "20px 0 6px", color: "var(--text-1)" }}>{inline(b.text)}</h2>;
      case "h3": return <h3 key={i} style={{ fontSize: 14, fontWeight: 700, margin: "14px 0 4px", color: "var(--text-2)" }}>{inline(b.text)}</h3>;
      case "p":  return <p  key={i} style={{ margin: "6px 0", color: "var(--text-2)", lineHeight: 1.7, fontSize: 13.5 }}>{inline(b.text)}</p>;
      case "ul":
      case "ol":
        return (
          <ul key={i} style={{
            margin: "6px 0", paddingLeft: 0, listStyle: "none",
            color: "var(--text-2)", lineHeight: 1.7, fontSize: 13.5
          }}>
            {b.items.map((it, j) => (
              <li key={j} style={{ display: "flex", gap: 10, padding: "2px 0" }}>
                <span className="mono" style={{ color: "var(--accent)", minWidth: 18 }}>
                  {b.kind === "ol" ? `${j + 1}.` : "•"}
                </span>
                <span>{inline(it)}</span>
              </li>
            ))}
          </ul>
        );
      case "quote": return (
        <blockquote key={i} style={{
          margin: "10px 0", padding: "8px 14px",
          borderLeft: "2px solid var(--accent)",
          color: "var(--text-2)", fontSize: 13.5, lineHeight: 1.7,
          background: "var(--accent-soft)"
        }}>{inline(b.text)}</blockquote>
      );
      case "code": return (
        <pre key={i} className="mono" style={{
          margin: "10px 0", padding: 12,
          background: "var(--bg-0)", border: "1px solid var(--border-s)",
          borderRadius: "var(--r-md)", color: "var(--text-2)",
          fontSize: 12.5, lineHeight: 1.6, overflowX: "auto"
        }}>{b.body}</pre>
      );
      case "spacer": return <div key={i} style={{ height: 4 }}/>;
      default: return null;
    }
  });
}

/* line numbers + naive syntax tinting for the editor */
function highlightLine(raw) {
  if (/^#+\s/.test(raw)) return <span style={{ color: "var(--good)" }}>{raw}</span>;
  if (/^>\s/.test(raw)) return <span style={{ color: "var(--info)" }}>{raw}</span>;
  if (/^[\-\*]\s/.test(raw) || /^\d+\.\s/.test(raw)) return <span style={{ color: "var(--accent)" }}>{raw}</span>;
  // bold + inline code
  const parts = raw.split(/(\*\*[^*]+\*\*|`[^`]+`)/g);
  return parts.map((p, i) => {
    if (p.startsWith("**") && p.endsWith("**"))
      return <span key={i} style={{ color: "var(--warn)" }}>{p}</span>;
    if (p.startsWith("`") && p.endsWith("`"))
      return <span key={i} style={{ color: "var(--info)" }}>{p}</span>;
    return <span key={i}>{p}</span>;
  });
}

function GuidelinesEditor() {
  const [files, setFiles] = useState(DEFAULT_FILES);
  const [activeName, setActiveName] = useState(files[0].name);
  const [mode, setMode] = useState("edit"); // "edit" | "preview" | "split"
  const active = files.find((f) => f.name === activeName);

  const setActiveContent = (text) =>
    setFiles((fs) => fs.map((f) => f.name === activeName ? { ...f, content: text, dirty: true } : f));

  const save = () =>
    setFiles((fs) => fs.map((f) => f.name === activeName
      ? { ...f, dirty: false, updatedAt: new Date().toLocaleString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) }
      : f));

  // Ctrl/Cmd+S to save
  useEffect(() => {
    const handler = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === "s") {
        e.preventDefault(); save();
      }
    };
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, [activeName]);

  return (
    <div style={{
      height: "100%", display: "grid",
      gridTemplateColumns: "260px 1fr",
      minHeight: 0,
    }}>
      {/* file list */}
      <aside style={{
        borderRight: "1px solid var(--border-s)",
        display: "flex", flexDirection: "column",
        background: "oklch(0.185 0.022 250)",
        minHeight: 0,
      }}>
        <div style={{
          padding: "16px 16px 10px",
          display: "flex", alignItems: "center", justifyContent: "space-between",
        }}>
          <span className="mono" style={{
            fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase",
            color: "var(--text-3)"
          }}>Guidelines</span>
          <div style={{ display: "flex", gap: 2 }}>
            <IconButton title="New file"><I.Plus size={14}/></IconButton>
            <IconButton title="Refresh"><I.Refresh size={14}/></IconButton>
          </div>
        </div>
        <div style={{ overflowY: "auto", padding: "4px 8px 12px", flex: 1, minHeight: 0 }}>
          {files.map((f) => {
            const isActive = f.name === activeName;
            return (
              <button key={f.name} onClick={() => setActiveName(f.name)}
                style={{
                  width: "100%", display: "flex", alignItems: "center", gap: 10,
                  padding: "8px 10px", marginBottom: 2,
                  background: isActive ? "var(--bg-2)" : "transparent",
                  border: "1px solid " + (isActive ? "var(--border-m)" : "transparent"),
                  borderRadius: "var(--r-sm)",
                  color: isActive ? "var(--text-1)" : "var(--text-2)",
                  fontSize: 13, textAlign: "left",
                  transition: "all 120ms ease",
                }}
                onMouseEnter={(e) => { if (!isActive) e.currentTarget.style.background = "var(--bg-1)"; }}
                onMouseLeave={(e) => { if (!isActive) e.currentTarget.style.background = "transparent"; }}
              >
                <I.File size={14} style={{ color: isActive ? "var(--accent)" : "var(--text-3)" }}/>
                <span style={{ flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                  {f.name}
                </span>
                {f.dirty && <span style={{
                  width: 6, height: 6, borderRadius: 999, background: "var(--accent)",
                  flex: "none"
                }}/>}
              </button>
            );
          })}
        </div>
        <div style={{
          padding: "10px 16px",
          borderTop: "1px solid var(--border-s)",
          fontSize: 11, color: "var(--text-4)",
        }} className="mono">
          {files.length} files · {files.filter(f=>f.dirty).length} unsaved
        </div>
      </aside>

      {/* editor pane */}
      <div style={{ display: "grid", gridTemplateRows: "auto 1fr auto", minHeight: 0 }}>
        {/* tab bar */}
        <div style={{
          display: "flex", alignItems: "center",
          padding: "10px 16px",
          borderBottom: "1px solid var(--border-s)",
          gap: 12,
        }}>
          <div style={{
            display: "flex", alignItems: "center", gap: 8,
            padding: "6px 12px",
            background: "var(--bg-1)",
            border: "1px solid var(--border-s)",
            borderRadius: "var(--r-sm)",
            fontSize: 13,
          }}>
            <I.File size={13} style={{ color: "var(--accent)" }}/>
            {active.name}
            {active.dirty && <span style={{ color: "var(--accent)", fontSize: 16, lineHeight: 0 }}>•</span>}
          </div>
          <span style={{ flex: 1 }}/>

          <Segmented value={mode} onChange={setMode} options={[
            { id: "edit",    label: "Edit",    icon: <I.Edit size={12}/> },
            { id: "split",   label: "Split",   icon: <I.Activity size={12}/> },
            { id: "preview", label: "Preview", icon: <I.Eye size={12}/> },
          ]}/>
          <Btn kind="primary" size="md" icon={<I.Save size={13}/>} onClick={save} disabled={!active.dirty}>
            Save
          </Btn>
        </div>

        {/* body */}
        <div style={{ minHeight: 0, display: "grid", gridTemplateColumns: mode === "split" ? "1fr 1fr" : "1fr" }}>
          {(mode === "edit" || mode === "split") && (
            <EditorPane content={active.content} onChange={setActiveContent}/>
          )}
          {(mode === "preview" || mode === "split") && (
            <PreviewPane content={active.content} split={mode === "split"}/>
          )}
        </div>

        {/* status bar */}
        <footer style={{
          display: "flex", alignItems: "center", gap: 18,
          padding: "8px 16px",
          borderTop: "1px solid var(--border-s)",
          fontSize: 11, color: "var(--text-3)",
        }} className="mono">
          <span>{active.content.split("\n").length} lines</span>
          <span>{active.content.length.toLocaleString()} chars</span>
          <span>UTF-8</span>
          <span>LF</span>
          <span style={{ color: "var(--accent)" }}>Markdown</span>
          <span style={{ flex: 1 }}/>
          <span>Last saved: {active.updatedAt}</span>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--good)" }}>
            <I.Check size={11}/> No errors
          </span>
        </footer>
      </div>
    </div>
  );
}

function Segmented({ value, onChange, options }) {
  return (
    <div style={{
      display: "inline-flex",
      padding: 2,
      background: "var(--bg-1)",
      border: "1px solid var(--border-s)",
      borderRadius: "var(--r-sm)",
    }}>
      {options.map((o) => {
        const active = value === o.id;
        return (
          <button key={o.id} onClick={() => onChange(o.id)} style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            padding: "5px 12px",
            background: active ? "var(--bg-3)" : "transparent",
            color: active ? "var(--text-1)" : "var(--text-3)",
            border: "none",
            borderRadius: 4,
            fontSize: 12, fontWeight: 600,
            transition: "all 120ms ease",
          }}>
            {o.icon}{o.label}
          </button>
        );
      })}
    </div>
  );
}

function EditorPane({ content, onChange }) {
  const ta = useRef(null);
  const overlay = useRef(null);
  const gutter = useRef(null);
  const lines = content.split("\n");
  const sync = () => {
    if (!ta.current) return;
    const s = ta.current.scrollTop;
    if (overlay.current) overlay.current.scrollTop = s;
    if (gutter.current)  gutter.current.scrollTop  = s;
  };
  return (
    <div style={{
      position: "relative",
      display: "grid", gridTemplateColumns: "56px 1fr",
      minHeight: 0,
      background: "oklch(0.175 0.022 250)",
      overflow: "hidden",
    }}>
      <div ref={gutter} className="mono" style={{
        overflow: "hidden",
        padding: "14px 8px 14px 0",
        textAlign: "right",
        color: "var(--text-4)",
        fontSize: 12.5,
        lineHeight: "20px",
        borderRight: "1px solid var(--border-s)",
        userSelect: "none",
      }}>
        {lines.map((_, i) => <div key={i}>{i + 1}</div>)}
        <div style={{ height: 200 }}/>
      </div>
      <div style={{ position: "relative", minHeight: 0 }}>
        <pre ref={overlay} className="mono" aria-hidden="true" style={{
          position: "absolute", inset: 0,
          margin: 0, padding: "14px 16px",
          fontSize: 12.5, lineHeight: "20px",
          color: "var(--text-2)",
          whiteSpace: "pre-wrap", wordBreak: "break-word",
          pointerEvents: "none", overflow: "hidden",
        }}>
          {lines.map((l, i) => <div key={i}>{l ? highlightLine(l) : "\u200B"}</div>)}
        </pre>
        <textarea
          ref={ta}
          value={content}
          onChange={(e) => onChange(e.target.value)}
          onScroll={sync}
          spellCheck={false}
          className="mono"
          style={{
            position: "absolute", inset: 0,
            width: "100%", height: "100%",
            background: "transparent", color: "transparent",
            caretColor: "var(--accent)",
            border: "none", outline: "none", resize: "none",
            padding: "14px 16px",
            fontSize: 12.5, lineHeight: "20px",
            whiteSpace: "pre-wrap", wordBreak: "break-word",
          }}
        />
      </div>
    </div>
  );
}

function PreviewPane({ content, split }) {
  return (
    <div style={{
      overflowY: "auto",
      borderLeft: split ? "1px solid var(--border-s)" : "none",
      padding: "28px 36px",
      background: "var(--bg-0)",
    }}>
      <div style={{ maxWidth: 720 }}>{renderMd(content)}</div>
    </div>
  );
}

window.GuidelinesEditor = GuidelinesEditor;
