// Field-level help registry for dashboard entity detail pages.
//
// FIELD_HELP maps a field key to { label, description, doc? }.
//   label       — human-readable field name (used as bold heading in help-tip)
//   description — one sentence explaining the field
//   doc         — optional anchor into /docs/ pages for "Learn more"
//
// fieldRow(key, value) → <tr> element with a help-tip-decorated key cell and
//   a value cell. Falls back to a plain key cell when key is not in FIELD_HELP.
//
// Usage:
//   import {fieldRow} from "./components/field-help.js";
//   const tbody = html`<tbody>${fields.map(([k,v]) => fieldRow(k,v))}</tbody>`;

import {HelpTip} from "./help-tip.js";   // ensures custom element is registered
import {API} from "./config.js";
void HelpTip; // silence unused-import linters

// ── Entity link registry ────────────────────────────────────────────────────
// Maps FK field names to fetch/URL/title resolution rules.
// getUrl receives (id, data) so slug-routed entities (repos) can use data.slug.
const FIELD_LINKS = {
  task_id: {
    apiUrl:   id => `${API}/tasks/${id}`,
    getUrl:   (id, _d) => `/tasks/${id}`,
    getTitle: d => d.title,
  },
  workstream_id: {
    apiUrl:   id => `${API}/workplans/${id}`,
    getUrl:   (id, _d) => `/workstreams/${id}`,
    getTitle: d => d.title || d.slug,
  },
  repo_id: {
    apiUrl:   id => `${API}/repos/by-id/${id}`,
    getUrl:   (_id, d) => `/repos/${d.slug}`,
    getTitle: d => d.name || d.slug,
  },
};

/**
 * Render an entity-reference value as a link with an async help-tip showing
 * the entity title. Falls back gracefully if the fetch fails.
 */
function _linkCell(key, id) {
  const rule = FIELD_LINKS[key];
  const shortId = String(id).slice(0, 8) + "…";

  const a = document.createElement("a");
  a.textContent = shortId;
  a.href = "#";
  a.style.fontFamily = "var(--monospace, monospace)";
  a.title = String(id); // full UUID as native tooltip while async loads

  fetch(rule.apiUrl(id))
    .then(r => r.ok ? r.json() : null)
    .then(data => {
      if (!data) return;
      const title = rule.getTitle(data);
      const url   = rule.getUrl(id, data);
      if (url) a.href = url;
      if (title) {
        const tip = document.createElement("help-tip");
        tip.setAttribute("label", title);
        tip.setAttribute("description", `${key.replace(/_id$/, "")} · ${id}`);
        a.replaceWith(tip);
        tip.appendChild(a);
      }
    })
    .catch(() => { /* leave plain link */ });

  return a;
}

export const FIELD_HELP = {
  // ── TokenEvent ─────────────────────────────────────────────────────────────
  id: {
    label: "ID",
    description: "Unique identifier for this token event (UUID v4).",
    doc: "/docs/reference#token-events",
  },
  tokens_in: {
    label: "Tokens In",
    description: "Number of input (prompt) tokens consumed in this event.",
    doc: "/docs/reference#token-events",
  },
  tokens_out: {
    label: "Tokens Out",
    description: "Number of output (completion) tokens generated in this event.",
    doc: "/docs/reference#token-events",
  },
  tokens_total: {
    label: "Tokens Total",
    description: "Sum of input and output tokens — total cost proxy for this event.",
    doc: "/docs/reference#token-events",
  },
  task_id: {
    label: "Task ID",
    description: "The task this token event was recorded against (if any).",
    doc: "/docs/tasks",
  },
  workstream_id: {
    label: "Workstream ID",
    description: "The workstream this event belongs to; auto-resolved from task if not set directly.",
    doc: "/docs/workstreams",
  },
  repo_id: {
    label: "Repo ID",
    description: "The managed repo this event is attributed to; auto-resolved from workstream.",
    doc: "/docs/repos",
  },
  session_id: {
    label: "Session ID",
    description: "Opaque identifier for the Claude Code session that produced this event.",
  },
  model: {
    label: "Model",
    description: "The Claude model used (e.g. claude-sonnet-4-6).",
    doc: "/docs/reference#models",
  },
  agent: {
    label: "Agent",
    description: "The agent persona that produced this event (e.g. custodian, ralph).",
    doc: "/docs/reference#agents",
  },
  ref_type: {
    label: "Ref Type",
    description: "What kind of entity the ref_id points to: task, commit, release, or session.",
    doc: "/docs/reference#token-events",
  },
  ref_id: {
    label: "Ref ID",
    description: "Free-form reference ID; interpretation depends on ref_type.",
    doc: "/docs/reference#token-events",
  },
  note: {
    label: "Note",
    description: "Quality tag: 'measured' = exact from status bar, 'userbased' = human-provided, 'workplan' = prorated, 'heuristic' = server fallback.",
    doc: "/docs/reference#token-note-taxonomy",
  },
  created_at: {
    label: "Created At",
    description: "Timestamp when this token event was recorded (UTC).",
  },

  // ── Workstream ──────────────────────────────────────────────────────────────
  slug: {
    label: "Slug",
    description: "URL-safe short identifier for this entity.",
  },
  title: {
    label: "Title",
    description: "Human-readable name for this workstream or task.",
  },
  status: {
    label: "Status",
    description: "Current lifecycle state. Tasks use wait, todo, progress, done, or cancel.",
    doc: "/docs/workstream-lifecycle",
  },
  topic_id: {
    label: "Topic ID",
    description: "The topic this workstream is grouped under.",
    doc: "/docs/reference#topics",
  },
  repo_goal_id: {
    label: "Repo Goal ID",
    description: "Optional link to a repo-level strategic goal this workstream advances.",
    doc: "/docs/goals",
  },

  // ── Task ───────────────────────────────────────────────────────────────────
  assignee: {
    label: "Assignee",
    description: "Who is responsible for completing this task (agent name or human).",
  },
  priority: {
    label: "Priority",
    description: "Relative urgency: high, medium, or low.",
  },
  due_date: {
    label: "Due Date",
    description: "Target completion date (ISO 8601).",
  },
  needs_human: {
    label: "Needs Human",
    description: "True if the task is waiting for human input or approval.",
    doc: "/interventions",
  },
  intervention_note: {
    label: "Intervention Note",
    description: "Why human intervention is required for this task.",
  },

  // ── Repo ───────────────────────────────────────────────────────────────────
  repo_slug: {
    label: "Repo Slug",
    description: "Short identifier for the repository (matches the git remote slug).",
    doc: "/docs/repos",
  },
  event_count: {
    label: "Event Count",
    description: "Total number of token events attributed to this entity.",
  },
  by_model: {
    label: "By Model",
    description: "Token totals broken down by Claude model.",
  },
  by_note: {
    label: "By Note",
    description: "Token totals broken down by quality tier (measured / workplan / heuristic).",
    doc: "/docs/reference#token-note-taxonomy",
  },
};

/**
 * Render a single key-value row for an entity detail table.
 * @param {string} key   — field name
 * @param {*}      value — field value (stringified automatically)
 * @returns {HTMLTableRowElement}
 */
export function fieldRow(key, value) {
  const tr = document.createElement("tr");

  // Key cell
  const tdKey = document.createElement("td");
  tdKey.style.cssText = "padding:0.3rem 0.8rem 0.3rem 0; white-space:nowrap; vertical-align:top; color:var(--theme-foreground-muted,#666); font-size:0.82rem;";

  const help = FIELD_HELP[key];
  if (help) {
    const tip = document.createElement("help-tip");
    tip.setAttribute("label", help.label);
    tip.setAttribute("description", help.description);
    if (help.doc) tip.setAttribute("doc", help.doc);
    tip.textContent = help.label;
    tdKey.appendChild(tip);
  } else {
    tdKey.textContent = key;
  }
  tr.appendChild(tdKey);

  // Value cell
  const tdVal = document.createElement("td");
  tdVal.style.cssText = "padding:0.3rem 0; font-size:0.82rem; word-break:break-all; vertical-align:top;";

  let display;
  if (value === null || value === undefined) {
    display = document.createElement("span");
    display.style.color = "var(--theme-foreground-faint,#aaa)";
    display.textContent = "—";
  } else if (key in FIELD_LINKS) {
    display = _linkCell(key, value);
  } else if (typeof value === "object") {
    display = document.createElement("pre");
    display.style.cssText = "margin:0; font-size:0.75rem; white-space:pre-wrap;";
    display.textContent = JSON.stringify(value, null, 2);
  } else {
    display = document.createElement("span");
    display.textContent = String(value);
  }
  tdVal.appendChild(display);
  tr.appendChild(tdVal);

  return tr;
}
