import {
  coverageRemediation,
  coverageWitnesses,
  formatExecutionContext,
} from "./outcome-presentation.js";
import type { CoverageOutcomeRecord, ReportCell } from "./types.js";

function escapeHtml(value: string): string {
  return value
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#39;");
}

function renderKeyValue(label: string, value: string, field?: string): string {
  const fieldAttr = field === undefined ? "" : ` data-outcome-field="${escapeHtml(field)}"`;
  return `<div${fieldAttr}><strong>${escapeHtml(label)}:</strong> ${escapeHtml(value)}</div>`;
}

function renderExecutionContext(outcome: CoverageOutcomeRecord, cellIndex: ReportCell[]): string {
  const formatted = formatExecutionContext(outcome.context);
  const browserContext = outcome.context.kind === "browser" ? outcome.context : undefined;
  const cell = browserContext === undefined
    ? undefined
    : cellIndex.find((entry) => entry.id === browserContext.cell.id);
  const rows = formatted.details
    .map((entry) => renderKeyValue(entry.label, entry.value))
    .join("");
  const browserRows = cell === undefined ? "" : [
    renderKeyValue("Route", cell.route, "route"),
    renderKeyValue("Role", cell.role, "role"),
    renderKeyValue("Viewport", `${String(cell.viewport.width)}×${String(cell.viewport.height)}`, "viewport"),
  ].join("");

  return `
    <section data-report-section="execution-context" aria-labelledby="execution-context-heading">
      <h2 id="execution-context-heading">Execution context</h2>
      ${renderKeyValue("Kind", formatted.kind)}
      ${rows}
      ${browserRows}
    </section>
  `;
}

function renderWitnesses(outcome: CoverageOutcomeRecord): string {
  const witnesses = coverageWitnesses(outcome);
  if (witnesses.length === 0) {
    return "";
  }

  const items = witnesses
    .map((witness) => {
      const artifact =
        witness.artifactPath === undefined
          ? ""
          : ` <span data-witness-artifact="${escapeHtml(witness.artifactPath)}">(${escapeHtml(
              witness.artifactPath,
            )})</span>`;
      const status =
        witness.status === undefined ? "" : ` (${escapeHtml(witness.status)})`;
      return `
        <li data-witness-kind="${escapeHtml(witness.kind)}" data-witness-id="${escapeHtml(witness.id)}">
          <strong>${escapeHtml(witness.kind)}</strong>:
          ${escapeHtml(witness.description)}${status}${artifact}
        </li>
      `;
    })
    .join("");

  return `
    <section data-report-section="witnesses" aria-labelledby="witnesses-heading">
      <h2 id="witnesses-heading">Witnesses</h2>
      <ul>${items}</ul>
    </section>
  `;
}

function renderScope(outcome: CoverageOutcomeRecord): string {
  const parts = [outcome.scope.id];
  if (outcome.scope.detectorId !== undefined) {
    parts.push(`detector=${outcome.scope.detectorId}`);
  }
  if (outcome.scope.surfaceId !== undefined) {
    parts.push(`surface=${outcome.scope.surfaceId}`);
  }
  return renderKeyValue("Scope", parts.join(", "), "scope");
}

function renderCapabilityProfile(outcome: CoverageOutcomeRecord): string {
  if (outcome.capabilityProfileRef === undefined) {
    return renderKeyValue("Capability profile", "not recorded", "capability-profile");
  }
  return renderKeyValue(
    "Capability profile",
    outcome.capabilityProfileRef.id,
    "capability-profile",
  );
}

export function renderCoverageView(outcome: CoverageOutcomeRecord, cellIndex: ReportCell[]): string {
  return `
    <article
      class="outcome-view coverage-view"
      data-report-view="coverage"
      data-outcome-id="${escapeHtml(outcome.id)}"
      data-adjudicable="false"
      data-non-adjudicable="true"
    >
      <header class="outcome-header">
        <h1>Coverage incomplete</h1>
        <p class="non-adjudicable-banner" role="note">
          Non-adjudicable coverage outcome. Resolve by restoring requested evidence or changing scope.
        </p>
      </header>

      ${renderScope(outcome)}
      ${renderExecutionContext(outcome, cellIndex)}
      ${renderKeyValue("Reason", outcome.reason, "reason")}
      ${outcome.interaction === undefined ? "" : `${renderKeyValue("Gap kind", outcome.interaction.gapKind, "gap-kind")}${renderKeyValue("Control", `${outcome.interaction.control.accessibleName} (${outcome.interaction.control.locator})`, "control")}`}
      ${renderWitnesses(outcome)}
      ${renderCapabilityProfile(outcome)}
      ${renderKeyValue("Remediation", coverageRemediation(outcome.reason), "remediation")}
    </article>
  `;
}
