// Detail panel — agent profile + crons

// Relative-time formatter for "última execução …"
const timeAgo = (iso) => {
  if (!iso) return null;
  const d = new Date(iso);
  if (isNaN(d.getTime())) return null;
  const s = Math.floor((Date.now() - d.getTime()) / 1000);
  if (s < 0) return d.toLocaleString('pt-BR');
  if (s < 45) return 'agora mesmo';
  if (s < 3600) return `há ${Math.floor(s / 60)} min`;
  if (s < 86400) return `há ${Math.floor(s / 3600)} h`;
  if (s < 604800) return `há ${Math.floor(s / 86400)} d`;
  return d.toLocaleDateString('pt-BR');
};

// Returns "green" | "yellow" | "red" | "gray" given an agent.
const computeStatusColor = (agent) => {
  if (!agent || !agent.last_run_at) return "gray";
  const lastMs = Date.parse(agent.last_run_at);
  if (isNaN(lastMs)) return "gray";
  const ageMs = Date.now() - lastMs;
  const hours = ageMs / (1000 * 60 * 60);
  // Atraso vs cron: se cron_next_at já passou faz mais de 30min, está atrasado
  if (agent.cron_next_at) {
    const nextMs = Date.parse(agent.cron_next_at);
    if (!isNaN(nextMs) && Date.now() - nextMs > 30 * 60 * 1000) return "red";
  }
  if (hours < 1) return "green";
  if (hours < 24) return "yellow";
  return "red";
};

const formatNextRun = (iso) => {
  if (!iso) return null;
  const ms = Date.parse(iso);
  if (isNaN(ms)) return null;
  const d = new Date(ms);
  const today = new Date();
  const sameDay = d.toDateString() === today.toDateString();
  const tomorrow = new Date(today); tomorrow.setDate(today.getDate() + 1);
  const isTomorrow = d.toDateString() === tomorrow.toDateString();
  const hh = String(d.getHours()).padStart(2, "0");
  const mm = String(d.getMinutes()).padStart(2, "0");
  if (sameDay) return `hoje ${hh}:${mm}`;
  if (isTomorrow) return `amanhã ${hh}:${mm}`;
  return d.toLocaleDateString("pt-BR") + ` ${hh}:${mm}`;
};

// ── Toast ─────────────────────────────────────────────────────────────────────
const Toast = ({ msg, onDone }) => {
  React.useEffect(() => {
    const t = setTimeout(onDone, 2800);
    return () => clearTimeout(t);
  }, [onDone]);
  return <div className="toast">{msg}</div>;
};

// ── Edit Modal ────────────────────────────────────────────────────────────────
const EditModal = ({ agent, onClose }) => {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);
  return (
  <div className="modal-overlay" onClick={onClose}>
    <div className="modal" onClick={e => e.stopPropagation()}>
      <div className="modal-header">
        <h2>Editar agente</h2>
        <button className="icon-btn" onClick={onClose}><Icon name="x" size={15}/></button>
      </div>
      <dl className="kv" style={{gap: 10}}>
        <dt>ID</dt><dd><code>{agent.id}</code></dd>
        <dt>Nome</dt><dd>{agent.name}</dd>
        <dt>Modelo</dt><dd>{agent.model || "—"}</dd>
        <dt>Origem</dt><dd>{agent.origin || "—"}</dd>
        <dt>Função</dt><dd style={{whiteSpace:"pre-wrap"}}>{agent.role || "—"}</dd>
        <dt>Integrações</dt>
        <dd><div className="chips">{(agent.integrations||[]).map(i => <span key={i} className="chip brand">{i}</span>)}</div></dd>
        <dt>Traços</dt>
        <dd><div className="chips">{(agent.traits||[]).map(t => <span key={t} className="chip purple">{t}</span>)}</div></dd>
      </dl>
      <p style={{marginTop:16, fontSize:12, color:"var(--d-fg-3)"}}>
        Edição de metadados via UI em breve. Por enquanto edite via <code>registry.yaml</code> no container.
      </p>
    </div>
  </div>
  );
};

// ── AgentHero ─────────────────────────────────────────────────────────────────
const AgentHero = ({ agent, onRunAgent, onRequestRun, onToast, isRunning = false }) => {
  const [showEdit, setShowEdit] = React.useState(false);
  const [paused, setPaused] = React.useState(false);

  if (!agent) return null;

  const Badge = window.ModelBadge;
  const isOffline = agent.status === 'offline';
  const lastRunDisplay = timeAgo(agent.last_run_at) || (agent.lastRun || null);
  const lastRunFailed = agent.last_exit_code != null && agent.last_exit_code !== 0;

  const statusColor = computeStatusColor(agent);
  const statusColorTitle = statusColor === "green" ? "Saudável (última execução < 1h)"
    : statusColor === "yellow" ? "Atenção (1–24h desde última execução)"
    : statusColor === "red" ? "Atrasado ou >24h sem execução"
    : "Sem dados de execução";
  const nextRunLabel = formatNextRun(agent.cron_next_at);

  const handlePause = () => {
    if (paused) {
      setPaused(false);
      onToast(`${agent.name} retomado.`);
    } else {
      setPaused(true);
      onToast(`${agent.name} pausado localmente.`);
    }
  };

  const handleRun = async () => {
    if (isRunning || isOffline) return;
    if (onRequestRun) {
      // Gated path: App opens ConfirmRunModal and calls handleRunAgent on confirm.
      onRequestRun(agent);
      return;
    }
    // Fallback path (AgentDrawer or any legacy caller that didn't pass onRequestRun):
    // preserve the original direct-dispatch behavior with toast feedback.
    onToast(`Disparando ${agent.name}…`);
    try {
      const result = await onRunAgent(agent);
      const reply = result?.reply || result?.response || result?.status || 'execução concluída';
      onToast(`${agent.name}: ${String(reply).slice(0, 140)}`);
    } catch (err) {
      onToast(`${agent.name} — falha: ${err?.message || 'erro ao executar'}`);
    }
  };

  return (
    <>
      <div className="agent-hero">
        {agent.photo ? (
          <img
            className="avatar avatar-photo avatar-large"
            src={agent.photo}
            alt={agent.name}
            onError={(e) => {
              const node = e.currentTarget;
              const fallback = document.createElement('div');
              fallback.className = 'avatar';
              fallback.style.background = agent.avatarColor || '';
              fallback.textContent = initials(agent.name);
              node.replaceWith(fallback);
            }}
          />
        ) : (
          <div className="avatar" style={{ background: agent.avatarColor }}>
            {initials(agent.name)}
          </div>
        )}
        <div className="hero-text">
          <h1>{agent.name}</h1>
          <div className="role-line">
            <span>{agent.role}</span>
            <span className="sep"></span>
            {Badge ? (
              <Badge model={agent.model} />
            ) : (
              <span>{agent.model || 'none'}</span>
            )}
            <span className="sep"></span>
            <span className="status-line">
              <span className={"status-dot status-" + statusColor} title={statusColorTitle}></span>
              {lastRunDisplay ? (
                <span title={agent.last_run_at || ''}>
                  última execução {lastRunDisplay}
                  {lastRunFailed ? ` · falhou (${agent.last_exit_code})` : ''}
                </span>
              ) : (
                <span>nunca executado</span>
              )}
              {agent.cron_next_at && nextRunLabel && (
                <>
                  <span className="sep"></span>
                  <span className="next-run-label">próxima: {nextRunLabel}</span>
                </>
              )}
            </span>
          </div>
        </div>
        <div className="hero-actions">
          <button className="btn" onClick={() => setShowEdit(true)}>
            <Icon name="edit" size={14}/> Editar
          </button>
          <button
            className={"btn" + (paused ? " warn-btn" : "")}
            onClick={handlePause}
            disabled={isOffline}
            title={isOffline ? "Agente offline — não pode pausar" : undefined}
          >
            <Icon name={paused ? "play" : "pause"} size={14}/>
            {paused ? " Retomar" : " Pausar"}
          </button>
          <button className="btn primary" onClick={handleRun} disabled={isRunning || isOffline}>
            <Icon name="play" size={14}/>
            {isRunning ? " Executando..." : " Executar agora"}
          </button>
        </div>
      </div>
      {showEdit && <EditModal agent={agent} onClose={() => setShowEdit(false)} />}
    </>
  );
};

const StatStrip = ({ agent, onStatClick }) => {
  if (!agent) return null;
  const handleClick = onStatClick ? onStatClick : null;
  return (
  <div className="stat-strip">
    <div
      className={"stat" + (handleClick ? " stat-clickable" : "")}
      onClick={handleClick ? () => handleClick('runs') : undefined}
      role={handleClick ? "button" : undefined}
      tabIndex={handleClick ? 0 : undefined}
      title={handleClick ? "Ver execuções recentes" : undefined}
    >
      <div className="stat-label">Execuções hoje</div>
      <div className="stat-value">{agent.runsToday}</div>
      <div className="stat-sub">média 7d: {agent.avg7d != null ? agent.avg7d : Math.round((agent.runsToday || 0) * 0.85)}</div>
    </div>
    <div
      className={"stat" + (handleClick ? " stat-clickable" : "")}
      onClick={handleClick ? () => handleClick('success') : undefined}
      role={handleClick ? "button" : undefined}
      tabIndex={handleClick ? 0 : undefined}
      title={handleClick ? "Ver execuções recentes" : undefined}
    >
      <div className="stat-label">Taxa de sucesso</div>
      <div className="stat-value">{agent.successRate}%</div>
      <div className="stat-sub">últimos 30 dias</div>
    </div>
    <div
      className={"stat" + (handleClick ? " stat-clickable" : "")}
      onClick={handleClick ? () => handleClick('pending') : undefined}
      role={handleClick ? "button" : undefined}
      tabIndex={handleClick ? 0 : undefined}
      title={handleClick ? "Ver execuções recentes" : undefined}
    >
      <div className="stat-label">Aguardando aprovação</div>
      <div className="stat-value" style={{color: agent.pendingApprovals > 0 ? "var(--d-yellow)" : null}}>
        {agent.pendingApprovals}
      </div>
      <div className="stat-sub">{agent.pendingApprovals > 0 ? "ação necessária" : "tudo limpo"}</div>
    </div>
    {/* TODO: per-agent 30-day cost sparkline — deferred from quick 260513-u6y; needs new endpoint GET /api/v1/agents/{id}/cost-buckets returning [{date, cents}] × 30, plus a small inline SVG chart component. */}
    <div
      className={"stat" + (handleClick ? " stat-clickable" : "")}
      onClick={handleClick ? () => handleClick('cost') : undefined}
      role={handleClick ? "button" : undefined}
      tabIndex={handleClick ? 0 : undefined}
      title={handleClick ? "Ver execuções recentes" : undefined}
    >
      <div className="stat-label">Custo · 30d</div>
      <div className="stat-value">
        {agent.cost_30d_cents && agent.cost_30d_cents > 0
          ? '$' + (agent.cost_30d_cents / 100).toFixed(2)
          : '—'}
      </div>
      <div className="stat-sub">últimos 30 dias</div>
    </div>
  </div>
  );
};

const ProfileCards = ({ agent }) => {
  if (!agent) return null;
  const Badge = window.ModelBadge;
  const hasPersona = agent.description || agent.personality || agent.quote;
  return (
  <div className="two-col">
    <div className="card">
      <div className="section-head" style={{marginBottom: 10}}>
        <h2>Função &amp; Personalidade</h2>
      </div>
      {hasPersona ? (
        <>
          <p className="persona" style={{marginBottom: 14}}>{agent.description}</p>
          <p className="persona"><em>Como ela escreve:</em> {agent.personality}</p>
          <span className="quote">"{agent.quote}"</span>
        </>
      ) : (
        <p className="persona" style={{color:"var(--d-fg-3)", fontStyle:"italic"}}>
          Sem descrição configurada. Adicione os campos <code>description</code>, <code>personality</code> e <code>quote</code> via edição.
        </p>
      )}
    </div>
    <div className="card">
      <div className="section-head" style={{marginBottom: 12}}>
        <h2>Identidade</h2>
      </div>
      <dl className="kv">
        <dt>Modelo</dt>
        <dd>
          {Badge && agent.model && agent.model !== 'none'
            ? <Badge model={agent.model} />
            : <span style={{color:"var(--d-fg-3)"}}>none</span>}
        </dd>
        <dt>Status</dt>
        <dd><span className={"pill " + agent.status}>{agent.statusLabel}</span></dd>
        <dt>Traços</dt>
        <dd><div className="chips">{agent.traits.map(t => {
          if (t.startsWith('schedule:')) {
            const expr = t.slice(9);
            const human = typeof window.cronToHuman === 'function' ? window.cronToHuman(expr) : expr;
            return <span key={t} className="chip purple" title={expr}>{human}</span>;
          }
          return <span key={t} className="chip purple">{t}</span>;
        })}</div></dd>
        <dt>Integrações</dt>
        <dd><div className="chips">{agent.capabilities.map(c => <span key={c} className="chip brand">{c}</span>)}</div></dd>
      </dl>
    </div>
  </div>
  );
};

// =====================================================================
// Cron section
// =====================================================================
const CronItem = ({ cron, onToggle, onEdit, onDelete }) => (
  <div className={"cron-item" + (cron.enabled ? "" : " paused")}>
    <button
      className={"cron-toggle" + (cron.enabled ? " on" : "")}
      onClick={() => onToggle(cron.id)}
      aria-label={cron.enabled ? "pausar" : "ativar"}
    />
    <div className="cron-body">
      <div className="cron-title">{cron.title}</div>
      <div className="cron-meta">
        <span>{cron.description}</span>
        <span>·</span>
        <span className="cron-expr">{cron.expr}</span>
        <span>·</span>
        <span>{cron.natural}</span>
      </div>
    </div>
    <div className="cron-next">
      <div className="countdown">{cron.enabled ? cron.countdown : "pausado"}</div>
      <div>{cron.enabled ? `próx · ${cron.next}` : "—"}</div>
    </div>
    <div className="row-actions">
      <button className="icon-btn" onClick={() => onEdit(cron.id)} title="Editar cron"><Icon name="edit" size={15}/></button>
      <button
        className="icon-btn"
        onClick={() => { if (window.confirm(`Deletar o cron "${cron.title}"?`)) onDelete(cron.id); }}
        title="Deletar cron"
      ><Icon name="trash" size={15}/></button>
    </div>
  </div>
);

// natural-language → cron expr (heuristic)
// Handles: "cada N min/h", "às HHh[:MM]", days of week, "dia útil",
// "dia N" (day-of-month) optionally "de <mês>", month name on its own.
const WEEKDAYS_PT = [
  ["domingo", 0], ["segunda", 1], ["terça", 2], ["terca", 2],
  ["quarta", 3], ["quinta", 4], ["sexta", 5], ["sábado", 6], ["sabado", 6],
];
const MONTHS_PT = [
  ["janeiro", 1], ["fevereiro", 2], ["março", 3], ["marco", 3], ["abril", 4],
  ["maio", 5], ["junho", 6], ["julho", 7], ["agosto", 8], ["setembro", 9],
  ["outubro", 10], ["novembro", 11], ["dezembro", 12],
  ["jan", 1], ["fev", 2], ["mar", 3], ["abr", 4], ["mai", 5], ["jun", 6],
  ["jul", 7], ["ago", 8], ["set", 9], ["out", 10], ["nov", 11], ["dez", 12],
];
const clamp = (n, lo, hi) => Math.max(lo, Math.min(hi, n | 0));

const guessCron = (txt) => {
  const t = (txt || "").toLowerCase().trim();
  if (!t) return "";

  const minM = t.match(/cada\s+(\d+)\s*min/);
  if (minM) return `*/${clamp(+minM[1], 1, 59)} * * * *`;
  const hourM = t.match(/cada\s+(\d+)\s*h(?:ora)?s?\b/);
  if (hourM) return `0 */${clamp(+hourM[1], 1, 23)} * * *`;

  // accepts "às 7", "às 7h", "às 7h30", "às 7:30", "às 14:00"
  const tm = t.match(/(?:às|as)\s+(\d{1,2})\s*(?:[:h]\s*(\d{2}))?\s*h?/);
  const time = tm ? `${tm[2] ? clamp(+tm[2], 0, 59) : 0} ${clamp(+tm[1], 0, 23)}` : "0 9";

  for (const [name, dow] of WEEKDAYS_PT) {
    if (t.includes(name)) return `${time} * * ${dow}`;
  }
  if (/dias?\s+[úu]te(?:is|l)|seg-?\s*sex/.test(t)) return `${time} * * 1-5`;

  const month = (() => { for (const [name, n] of MONTHS_PT) if (t.includes(name)) return n; return null; })();

  const domM = t.match(/\bdia\s+(\d{1,2})\b/);
  if (domM) return `${time} ${clamp(+domM[1], 1, 31)} ${month != null ? month : "*"} *`;
  if (month != null) return `${time} 1 ${month} *`;

  if (/todo\s+(?:o\s+)?dia|diariamente|todos\s+os\s+dias|cada\s+dia/.test(t)) return `${time} * * *`;
  if (tm) return `${time} * * *`;
  // fallback: if there's enough text, default to daily 9h
  if (t.length >= 5) return "0 9 * * *";
  return "";
};

const NewCronForm = ({ onAdd }) => {
  const [text, setText] = React.useState("");
  const expr = React.useMemo(() => guessCron(text), [text]);
  const canAdd = text.trim().length >= 3;
  return (
    <div className="new-cron">
      <h3><Icon name="sparkles" size={13}/> Novo cron</h3>
      <textarea
        placeholder={"Descreva o que quer automatizar...\nEx: todo domingo às 4h fazer resumo semanal\nEx: a cada 30 min checar emails com meu nome em CC"}
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
      <div className="expr-preview">
        <div className={"expr-out" + (expr ? "" : " empty")}>
          {expr || (canAdd ? "0 9 * * * (padrão: diário às 9h)" : "expressão aparece aqui")}
        </div>
        <button
          className="btn primary"
          disabled={!canAdd}
          style={{ opacity: canAdd ? 1 : 0.5 }}
          onClick={() => { onAdd(text, expr || "0 9 * * *"); setText(""); }}
        >
          <Icon name="plus" size={14}/> Adicionar
        </button>
      </div>
    </div>
  );
};

const CronSection = ({ agent, crons, onToggle, onDelete, onAdd }) => {
  const list = crons.filter(c => !agent || c.agentId === agent.id);
  const onEdit = () => {};

  return (
    <div className="section">
      <div className="section-head">
        <h2><Icon name="clock" size={15} style={{verticalAlign: -2, marginRight: 6}}/> Cron Registry</h2>
        <span className="meta">{list.length} agendamentos · {list.filter(c=>c.enabled).length} ativos</span>
      </div>
      <div className="cron-list">
        {list.map(c => (
          <CronItem key={c.id} cron={c}
            onToggle={onToggle} onEdit={onEdit} onDelete={onDelete} />
        ))}
        {list.length === 0 && (
          <div className="card" style={{textAlign: "center", color: "var(--d-fg-3)", padding: 24}}>
            <div style={{marginBottom: 12}}>Nenhum cron agendado para este agente ainda.</div>
            <div style={{fontSize: 12, marginBottom: 12, color: "var(--d-fg-3)"}}>Comece com um template:</div>
            <div className="chips" style={{justifyContent: "center", gap: 8}}>
              <button
                className="chip cron-template-chip"
                onClick={() => onAdd("Digest matinal", "0 8 * * *")}
                title="0 8 * * *"
              >
                <Icon name="clock" size={12}/> Digest 8h
              </button>
              <button
                className="chip cron-template-chip"
                onClick={() => onAdd("Varredura inbox", "0 */2 * * *")}
                title="0 */2 * * *"
              >
                <Icon name="activity" size={12}/> Varredura a cada 2h
              </button>
              <button
                className="chip cron-template-chip"
                onClick={() => onAdd("Resumo semanal", "0 9 * * 0")}
                title="0 9 * * 0"
              >
                <Icon name="calendar" size={12}/> Resumo semanal · domingo 9h
              </button>
            </div>
          </div>
        )}
      </div>
      <NewCronForm onAdd={onAdd} />
    </div>
  );
};

// ── ConfirmRunModal — gate "Executar agora" with a cost preview ────────────────
const ConfirmRunModal = ({ agent, onCancel, onConfirm, running }) => {
  if (!agent) return null;
  const cost = agent.last_run_cost_cents != null
    ? `~$${(agent.last_run_cost_cents / 100).toFixed(4)} (última run)`
    : "custo desconhecido — última run não rastreou tokens";
  const dangerous = agent.delegatable === false;
  return (
    <div className="modal-backdrop" onClick={onCancel}>
      <div className="modal-card" onClick={(e) => e.stopPropagation()} role="dialog" aria-modal="true">
        <div className="modal-head">
          <h2>Executar {agent.name}?</h2>
          <button className="icon-btn" onClick={onCancel} aria-label="Fechar"><Icon name="x" size={15}/></button>
        </div>
        <div className="modal-body">
          <dl className="kv">
            <dt>Modelo</dt><dd>{agent.model || "—"}</dd>
            <dt>Custo estimado</dt><dd>{cost}</dd>
          </dl>
          {dangerous && (
            <div className="modal-warning">
              <Icon name="alert-triangle" size={14}/> Este agente não é delegável — disparar manualmente pode causar efeitos colaterais (jobs cron pesados, side-effects externos).
            </div>
          )}
        </div>
        <div className="modal-actions">
          <button className="btn" onClick={onCancel} disabled={running}>Cancelar</button>
          <button className="btn primary" onClick={onConfirm} disabled={running}>
            {running ? "Executando..." : "Executar"}
          </button>
        </div>
      </div>
    </div>
  );
};

window.AgentHero = AgentHero;
window.StatStrip = StatStrip;
window.ProfileCards = ProfileCards;
window.CronSection = CronSection;
window.Toast = Toast;
window.computeStatusColor = computeStatusColor;
window.ConfirmRunModal = ConfirmRunModal;
