// Task detail drawer — chain-of-thought rendered as message history,
// composer for follow-up, decision block, fork action.

function estTokens(text) {
  if (!text) return 0;
  return Math.ceil(String(text).length / 4);
}

function stepTokens(step) {
  let t = 8;
  if (step.text) t += estTokens(step.text);
  if (step.tool) t += estTokens(step.tool) + 6;
  return t;
}

function totalContextTokens(task, agent) {
  const sysText = (window.AGENT_INSTRUCTIONS || {})[agent ? agent.id : ""] || "";
  const sysTok = estTokens(sysText);
  const taskTok = estTokens(task.title || "") + estTokens(task.description || "") + 12;
  const stepsTok = (task.cot || []).reduce((acc, s) => acc + stepTokens(s), 0);
  return { sys: sysTok, task: taskTok, steps: stepsTok, total: sysTok + taskTok + stepsTok };
}

const KIND_TO_ROLE = {
  thought: "assistant",
  tool: "assistant",
  output: "tool",
  wait: "assistant",
  decision: "assistant",
  user: "user",
  system: "system",
};

const ROLE_LABELS = {
  user: "user",
  assistant: "assistant",
  tool: "tool",
  system: "system",
};

function MessageRow({ step, idx, agentId, isLast }) {
  const [open, setOpen] = React.useState(true);
  const a = step.agent ? (window.AGENTS || {})[step.agent] : null;
  const role = step.role || KIND_TO_ROLE[step.kind] || "assistant";
  const tokens = stepTokens(step);

  const KindIcon = {
    thought: window.Icon.Sparkle,
    tool: window.Icon.Tool,
    output: window.Icon.Output,
    wait: window.Icon.Wait,
    decision: window.Icon.Decision,
  }[step.kind] || window.Icon.Dot;

  return (
    <div className={"msg msg-role-" + role + " msg-kind-" + (step.kind || "user")}>
      <div className="msg-rail">
        <div className="msg-dot kind-icon-wrap"><KindIcon /></div>
        {!isLast && <div className="msg-line" />}
      </div>
      <div className="msg-body">
        <div className="msg-head">
          <span className="msg-role">{ROLE_LABELS[role]}</span>
          {a && (
            <span className="msg-author">
              <window.Avatar who={a.id} size={14} />
              {a.name}
            </span>
          )}
          {step.kind && step.kind !== "user" && (
            <span className="msg-kind-tag">{step.kind}</span>
          )}
          {step.tool && (
            <span className="msg-tool-name mono">{step.tool}</span>
          )}
          <div style={{ flex: 1 }} />
          <span className="msg-tokens mono" title={`${tokens} tokens`}>{tokens} tok</span>
          <span className="msg-time mono">{step.t ? new Date(step.t * 1000).toLocaleTimeString().slice(0,5) : ""}</span>
          <div className="msg-actions">
            <button className="msg-action" onClick={() => setOpen(!open)}>{open ? "–" : "+"}</button>
          </div>
        </div>
        {open && (
          <div className="msg-content">
            {step.kind === "tool" ? (
              <div className="msg-tool-call mono">
                <span className="tname">{step.tool}</span>
                <span className="dim">·</span>
                <span style={{ whiteSpace: "pre-wrap" }}>{step.text}</span>
              </div>
            ) : step.kind === "decision" ? (
              <div className="msg-text" style={{ whiteSpace: "pre-wrap", color: "var(--warn-text)" }}>
                <strong>Decision needed:</strong> {step.text}
              </div>
            ) : step.kind === "user" ? (
              <div className="msg-text" style={{ whiteSpace: "pre-wrap" }}>
                <strong>You:</strong> {step.text}
              </div>
            ) : step.kind === "thought" ? (
              <div className="msg-text msg-md" dangerouslySetInnerHTML={window.renderMarkdown(step.text)} />
            ) : step.kind === "output" ? (
              <div className="msg-text msg-md" dangerouslySetInnerHTML={window.renderMarkdown(step.text)} />
            ) : (
              <div className="msg-text" style={{ whiteSpace: "pre-wrap" }}>{step.text}</div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

function ContextMeter({ tokens, ctxWindow }) {
  const pct = Math.min(100, (tokens.total / ctxWindow) * 100);
  const cls = pct > 80 ? "warn" : pct > 60 ? "high" : "ok";
  return (
    <div className={"ctx-meter ctx-" + cls}>
      <div className="ctx-row">
        <span className="ctx-label">Context</span>
        <span className="ctx-value mono">{tokens.total.toLocaleString()} / {ctxWindow.toLocaleString()}</span>
        <span className="ctx-pct mono">{pct.toFixed(1)}%</span>
      </div>
      <div className="ctx-bar">
        <div className="ctx-bar-fill ctx-sys"  style={{ width: (tokens.sys / ctxWindow * 100) + "%" }} />
        <div className="ctx-bar-fill ctx-task" style={{ width: (tokens.task / ctxWindow * 100) + "%" }} />
        <div className="ctx-bar-fill ctx-msgs" style={{ width: (tokens.steps / ctxWindow * 100) + "%" }} />
      </div>
      <div className="ctx-legend mono">
        <span><i className="dot ctx-sys" />system {tokens.sys}</span>
        <span><i className="dot ctx-task" />task {tokens.task}</span>
        <span><i className="dot ctx-msgs" />messages {tokens.steps}</span>
      </div>
    </div>
  );
}

function pendingInputFor(task) {
  if (!task || !task.decision_request_id) return null;
  return (window.PENDING_INPUT || []).find((r) => r.request_id === task.decision_request_id) || null;
}

function DecisionBlock({ task, picked, onPick, answer, setAnswer, onSubmitAnswer, onSubmitConfirm }) {
  if (!task || !task.needs_decision) return null;
  const req = pendingInputFor(task);
  const inputType = (req && req.input_type) || (task.decision_options && task.decision_options.length ? "choice" : "text");
  const opts = task.decision_options || (req && req.choices) || [];
  const titleByType = {
    confirm: "Approval needed",
    text: "The agent has a question for you",
    choice: "Pick one option",
  };
  return (
    <div className="decision-card">
      <div className="decision-card-title">
        <window.Icon.Decision />
        {titleByType[inputType] || "Input needed"}
      </div>
      <div className="decision-prompt" style={{ whiteSpace: "pre-wrap" }}>{task.decision_prompt}</div>

      {inputType === "choice" && opts.length > 0 && (
        <>
          <div className="decision-options">
            {opts.map((opt, i) => (
              <button
                key={i}
                className={"decision-opt" + (picked === i ? " picked" : "")}
                onClick={() => onPick(i)}
              >
                <span className="num">{String.fromCharCode(65 + i)}</span>
                <span>{String(opt)}</span>
              </button>
            ))}
          </div>
          <div className="decision-inline-actions">
            <button
              className="btn primary"
              disabled={picked == null}
              style={{ opacity: picked == null ? 0.45 : 1 }}
              onClick={() => onSubmitConfirm(true)}
            >
              Confirm choice
            </button>
            <button className="btn ghost" onClick={() => onSubmitConfirm(false)}>Reject</button>
          </div>
        </>
      )}

      {inputType === "text" && (
        <>
          <textarea
            className="decision-text-input"
            placeholder="Type your answer here…"
            value={answer}
            onChange={(e) => setAnswer(e.target.value)}
            rows={3}
            autoFocus
            onKeyDown={(e) => {
              if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
                e.preventDefault();
                onSubmitAnswer();
              }
            }}
          />
          <div className="decision-inline-actions">
            <span className="muted-sub mono" style={{ fontSize: 11 }}>⌘↵ to send</span>
            <div style={{ flex: 1 }} />
            <button
              className="btn primary"
              disabled={!answer.trim()}
              style={{ opacity: answer.trim() ? 1 : 0.45 }}
              onClick={onSubmitAnswer}
            >
              Send answer
            </button>
          </div>
        </>
      )}

      {inputType === "confirm" && (
        <div className="decision-inline-actions">
          <button className="btn primary" onClick={() => onSubmitConfirm(true)}>Approve</button>
          <button className="btn ghost" onClick={() => onSubmitConfirm(false)}>Deny</button>
        </div>
      )}
    </div>
  );
}

function TaskDrawer({ task, project, onClose, onOpenAgent }) {
  const [picked, setPicked] = React.useState(null);
  const [comment, setComment] = React.useState("");
  const [answer, setAnswer] = React.useState("");

  React.useEffect(() => {
    setPicked(null);
    setComment("");
    setAnswer("");
    const onKey = (e) => { if (e.key === "Escape" && task) onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [task]);

  const open = !!task;
  const a = task ? (window.AGENTS || {})[task.assignee] : null;
  const colTitle = task ? ((window.COLUMNS || []).find((c) => c.id === task.column) || {}).title : "";
  const ctxWindow = (a && a.contextWindow) || 200000;
  const tokens = task ? totalContextTokens(task, a) : { sys: 0, task: 0, steps: 0, total: 0 };

  const req = pendingInputFor(task);
  const inputType = (req && req.input_type) || (task && task.decision_options && task.decision_options.length ? "choice" : null);

  const sendComment = async () => {
    const text = comment.trim();
    if (!text || !task) return;
    await window.api.commentTask(task.id, text);
    setComment("");
  };

  const sendAnswer = async () => {
    const text = answer.trim();
    if (!text || !task || !task.decision_request_id) return;
    await window.api.respondInput(task.decision_request_id, { approved: true, value: text });
    setAnswer("");
  };

  const confirmDecision = async (approved) => {
    if (!task || !task.decision_request_id) return;
    let value = "";
    if (inputType === "choice") {
      const opts = task.decision_options || (req && req.choices) || [];
      if (picked != null && opts[picked]) value = String(opts[picked]);
    }
    await window.api.respondInput(task.decision_request_id, { approved, value });
    setPicked(null);
  };

  const fork = async () => {
    if (!task) return;
    await window.api.forkTask(task.id);
  };

  return (
    <>
      <div className={"drawer-scrim" + (open ? " open" : "")} onClick={onClose} />
      <div className={"drawer drawer-wide" + (open ? " open" : "")}>
        {task && (
          <>
            <div className="drawer-head">
              <span className="card-id">{(project && project.name) || ""} · {task.id ? task.id.slice(0, 6) : ""}</span>
              <div style={{ flex: 1 }} />
              {task.active && <span className="live-dot" />}
              <button className="drawer-close" onClick={onClose}><window.Icon.Close /></button>
            </div>

            <div className="drawer-body">
              <div className="drawer-title">{task.title}</div>
              {task.description && <div className="drawer-desc">{task.description}</div>}

              <DecisionBlock
                task={task}
                picked={picked}
                onPick={setPicked}
                answer={answer}
                setAnswer={setAnswer}
                onSubmitAnswer={sendAnswer}
                onSubmitConfirm={confirmDecision}
              />

              <div className="drawer-section">
                <h3>Details</h3>
                <dl className="meta-grid">
                  <dt>Status</dt>
                  <dd>{colTitle}</dd>
                  <dt>Assignee</dt>
                  <dd
                    onClick={() => a && a.kind === "ai" && onOpenAgent && onOpenAgent(a.id)}
                    style={{ cursor: a && a.kind === "ai" ? "pointer" : "default" }}
                  >
                    {a ? (
                      <>
                        <window.Avatar who={task.assignee} size={20} />
                        <span style={a && a.kind === "ai" ? { textDecoration: "underline", textUnderlineOffset: "3px" } : {}}>{a.name}</span>
                        {a.kind === "ai" && (
                          <span className="label-pill" style={{ color: "var(--ai)" }}>AI · {a.role}</span>
                        )}
                      </>
                    ) : <span style={{ color: "var(--text-faint)" }}>unassigned</span>}
                  </dd>
                  {a && a.kind === "ai" && (<>
                    <dt>Model</dt>
                    <dd>
                      <span className="model-chip"><window.Icon.Sparkle /><span className="mono">{a.model}</span></span>
                      <span style={{ color: "var(--text-muted)", fontSize: 12 }}>{a.provider}</span>
                    </dd>
                    <dt>Latency</dt>
                    <dd className="mono" style={{ color: "var(--text-muted)" }}>
                      <span style={{ color: "var(--text)" }}>{Math.round(a.ttftMs || a.avgLatencyMs || 0)}</span> ms TTFT
                      <span> · </span>
                      <span style={{ color: "var(--text)" }}>{(a.tps || 0).toFixed(0)}</span> tok/s
                    </dd>
                  </>)}
                  {task.usage && (task.usage.tokens_in + task.usage.tokens_out > 0) && (<>
                    <dt>Tokens</dt>
                    <dd className="mono" style={{ color: "var(--text-muted)" }}>
                      <span style={{ color: "var(--text)" }}>{(task.usage.tokens_in || 0).toLocaleString()}</span> in
                      <span> · </span>
                      <span style={{ color: "var(--text)" }}>{(task.usage.tokens_out || 0).toLocaleString()}</span> out
                      <span style={{ marginLeft: 8, padding: "1px 7px", borderRadius: 5, background: "var(--bg-sunken)", border: "1px solid var(--border)", color: "var(--text)" }}>${(task.usage.cost || 0).toFixed(4)}</span>
                      <span style={{ color: "var(--text-faint)" }}>· {task.usage.runs || 0} runs</span>
                    </dd>
                  </>)}
                  {task.labels && task.labels.length > 0 && (<>
                    <dt>Labels</dt>
                    <dd>{task.labels.map((l) => <span key={l} className="label-pill">{l}</span>)}</dd>
                  </>)}
                </dl>
              </div>

              {a && a.kind === "ai" && (
                <div className="drawer-section">
                  <div className="ctx-header">
                    <h3 style={{ margin: 0 }}>Message history</h3>
                    <span className="muted-sub">1:1 with what {a.name}'s LLM sees</span>
                    <div style={{ flex: 1 }} />
                    <button className="btn ghost" onClick={fork} title="Fork this task into a new project">Fork</button>
                  </div>
                  <ContextMeter tokens={tokens} ctxWindow={ctxWindow} />
                </div>
              )}

              <div className="drawer-section">
                {(!task.cot || task.cot.length === 0) ? (
                  <div className="empty-cot">No messages yet. Add one below to kick off the agent.</div>
                ) : (
                  <div className="msg-list">
                    {a && a.kind === "ai" && (
                      <div className="msg msg-role-system msg-kind-system">
                        <div className="msg-rail">
                          <div className="msg-dot"><window.Icon.Dot /></div>
                          <div className="msg-line" />
                        </div>
                        <div className="msg-body">
                          <div className="msg-head">
                            <span className="msg-role">system</span>
                            <span className="msg-kind-tag">instructions</span>
                            <div style={{ flex: 1 }} />
                            <span className="msg-tokens mono">{tokens.sys} tok</span>
                          </div>
                          <div className="msg-content">
                            <div className="msg-text msg-text-clamped">{((window.AGENT_INSTRUCTIONS || {})[a.id] || "").split("\n").slice(0, 4).join("\n")}…</div>
                            <div className="msg-readonly-note">Edit in <strong>Configure → Instructions</strong></div>
                          </div>
                        </div>
                      </div>
                    )}
                    <div className="msg msg-role-user msg-kind-user">
                      <div className="msg-rail">
                        <div className="msg-dot"><window.Icon.Dot /></div>
                        <div className="msg-line" />
                      </div>
                      <div className="msg-body">
                        <div className="msg-head">
                          <span className="msg-role">user</span>
                          <span className="msg-kind-tag">task</span>
                          <div style={{ flex: 1 }} />
                          <span className="msg-tokens mono">{tokens.task} tok</span>
                        </div>
                        <div className="msg-content">
                          <div className="msg-text"><strong>{task.title}</strong></div>
                          {task.description && <div className="msg-text" style={{ color: "var(--text-muted)" }}>{task.description}</div>}
                        </div>
                      </div>
                    </div>
                    {task.cot.map((s, i) => (
                      <MessageRow
                        key={i}
                        step={s}
                        idx={i}
                        agentId={a && a.id}
                        isLast={i === task.cot.length - 1}
                      />
                    ))}
                  </div>
                )}
              </div>

              <div className="composer">
                <div className="composer-head">
                  <span className="msg-role">
                    {inputType === "text" ? "your answer" : "your comment"}
                  </span>
                  <span className="muted-sub">
                    {inputType === "text"
                      ? "the agent is paused, waiting for your reply"
                      : "added as a user message and re-runs the agent"}
                  </span>
                  <div style={{ flex: 1 }} />
                  <span className="msg-tokens mono">{estTokens(comment)} tok</span>
                </div>
                <textarea
                  className="composer-input"
                  placeholder={inputType === "text"
                    ? "Type your answer to the question above…"
                    : `Reply to ${a ? a.name : "the agent"}…`}
                  value={comment}
                  onChange={(e) => setComment(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); sendComment(); }
                  }}
                  rows={3}
                  autoFocus={inputType === "text"}
                />
                <div className="composer-foot">
                  <span className="muted-sub mono">⌘↵ to send</span>
                  <div style={{ flex: 1 }} />
                  <button className="btn primary" disabled={!comment.trim()} style={{ opacity: comment.trim() ? 1 : 0.4 }} onClick={sendComment}>
                    {inputType === "text"
                      ? "Send answer"
                      : `Send to ${a ? a.name : "agent"}`}
                  </button>
                </div>
              </div>
            </div>

            <div className="drawer-actions">
              <button className="btn" onClick={fork}>Fork</button>
              <select
                className="btn"
                value={task.column}
                onChange={async (e) => { await window.api.moveTask(task.id, e.target.value); }}
                title="Move to column"
              >
                {(window.COLUMNS || []).map((c) => (
                  <option key={c.id} value={c.id}>Move → {c.title}</option>
                ))}
              </select>
              <div style={{ flex: 1 }} />
              <button
                className="btn danger"
                onClick={async () => {
                  const ok = await window.dialog.confirm({
                    title: "Delete this task?",
                    body: `“${task.title}” and its message history will be removed. This can't be undone.`,
                    confirmLabel: "Delete task",
                    danger: true,
                  });
                  if (ok) {
                    await window.api.deleteTask(task.id);
                    onClose();
                  }
                }}
              >
                Delete
              </button>
            </div>
          </>
        )}
      </div>
    </>
  );
}

window.TaskDrawer = TaskDrawer;
