import type { ProgressReporter } from "../../cli/progress.js";
import { renderTable } from "../../terminal/table.js";
import { isRich, theme } from "../../terminal/theme.js";
import { appendStatusAllDiagnosis } from "./diagnosis.js";
import { formatTimeAgo } from "./format.js";

type OverviewRow = { Item: string; Value: string };

type ChannelsTable = {
  rows: Array<{
    id: string;
    label: string;
    enabled: boolean;
    state: "ok" | "warn" | "off" | "setup";
    detail: string;
  }>;
  details: Array<{
    title: string;
    columns: string[];
    rows: Array<Record<string, string>>;
  }>;
};

type ChannelIssueLike = {
  channel: string;
  message: string;
};

type AgentStatusLike = {
  agents: Array<{
    id: string;
    name?: string | null;
    bootstrapPending?: boolean | null;
    sessionsCount: number;
    lastActiveAgeMs?: number | null;
    sessionsPath: string;
  }>;
};

export async function buildStatusAllReportLines(params: {
  progress: ProgressReporter;
  overviewRows: OverviewRow[];
  channels: ChannelsTable;
  channelIssues: ChannelIssueLike[];
  agentStatus: AgentStatusLike;
  connectionDetailsForReport: string;
  diagnosis: Omit<
    Parameters<typeof appendStatusAllDiagnosis>[0],
    "lines" | "progress" | "muted" | "ok" | "warn" | "fail" | "connectionDetailsForReport"
  >;
}) {
  const rich = isRich();
  const heading = (text: string) => (rich ? theme.heading(text) : text);
  const ok = (text: string) => (rich ? theme.success(text) : text);
  const warn = (text: string) => (rich ? theme.warn(text) : text);
  const fail = (text: string) => (rich ? theme.error(text) : text);
  const muted = (text: string) => (rich ? theme.muted(text) : text);

  const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1);

  const overview = renderTable({
    width: tableWidth,
    columns: [
      { key: "Item", header: "Item", minWidth: 10 },
      { key: "Value", header: "Value", flex: true, minWidth: 24 },
    ],
    rows: params.overviewRows,
  });

  const channelRows = params.channels.rows.map((row) => ({
    channelId: row.id,
    Channel: row.label,
    Enabled: row.enabled ? ok("ON") : muted("OFF"),
    State:
      row.state === "ok"
        ? ok("OK")
        : row.state === "warn"
          ? warn("WARN")
          : row.state === "off"
            ? muted("OFF")
            : theme.accentDim("SETUP"),
    Detail: row.detail,
  }));
  const channelIssuesByChannel = (() => {
    const map = new Map<string, ChannelIssueLike[]>();
    for (const issue of params.channelIssues) {
      const key = issue.channel;
      const list = map.get(key);
      if (list) {
        list.push(issue);
      } else {
        map.set(key, [issue]);
      }
    }
    return map;
  })();
  const channelRowsWithIssues = channelRows.map((row) => {
    const issues = channelIssuesByChannel.get(row.channelId) ?? [];
    if (issues.length === 0) {
      return row;
    }
    const issue = issues[0];
    const suffix = ` · ${warn(`gateway: ${String(issue.message).slice(0, 90)}`)}`;
    return {
      ...row,
      State: warn("WARN"),
      Detail: `${row.Detail}${suffix}`,
    };
  });

  const channelsTable = renderTable({
    width: tableWidth,
    columns: [
      { key: "Channel", header: "Channel", minWidth: 10 },
      { key: "Enabled", header: "Enabled", minWidth: 7 },
      { key: "State", header: "State", minWidth: 8 },
      { key: "Detail", header: "Detail", flex: true, minWidth: 28 },
    ],
    rows: channelRowsWithIssues,
  });

  const agentRows = params.agentStatus.agents.map((a) => ({
    Agent: a.name?.trim() ? `${a.id} (${a.name.trim()})` : a.id,
    BootstrapFile:
      a.bootstrapPending === true
        ? warn("PRESENT")
        : a.bootstrapPending === false
          ? ok("ABSENT")
          : "unknown",
    Sessions: String(a.sessionsCount),
    Active: a.lastActiveAgeMs != null ? formatTimeAgo(a.lastActiveAgeMs) : "unknown",
    Store: a.sessionsPath,
  }));

  const agentsTable = renderTable({
    width: tableWidth,
    columns: [
      { key: "Agent", header: "Agent", minWidth: 12 },
      { key: "BootstrapFile", header: "Bootstrap file", minWidth: 14 },
      { key: "Sessions", header: "Sessions", align: "right", minWidth: 8 },
      { key: "Active", header: "Active", minWidth: 10 },
      { key: "Store", header: "Store", flex: true, minWidth: 34 },
    ],
    rows: agentRows,
  });

  const lines: string[] = [];
  lines.push(heading("OpenClaw status --all"));
  lines.push("");
  lines.push(heading("Overview"));
  lines.push(overview.trimEnd());
  lines.push("");
  lines.push(heading("Channels"));
  lines.push(channelsTable.trimEnd());
  for (const detail of params.channels.details) {
    lines.push("");
    lines.push(heading(detail.title));
    lines.push(
      renderTable({
        width: tableWidth,
        columns: detail.columns.map((c) => ({
          key: c,
          header: c,
          flex: c === "Notes",
          minWidth: c === "Notes" ? 28 : 10,
        })),
        rows: detail.rows.map((r) => ({
          ...r,
          ...(r.Status === "OK"
            ? { Status: ok("OK") }
            : r.Status === "WARN"
              ? { Status: warn("WARN") }
              : {}),
        })),
      }).trimEnd(),
    );
  }
  lines.push("");
  lines.push(heading("Agents"));
  lines.push(agentsTable.trimEnd());
  lines.push("");
  lines.push(heading("Diagnosis (read-only)"));

  await appendStatusAllDiagnosis({
    lines,
    progress: params.progress,
    muted,
    ok,
    warn,
    fail,
    connectionDetailsForReport: params.connectionDetailsForReport,
    ...params.diagnosis,
  });

  return lines;
}
