import type { DecisionScope } from "../../schema/src/decisions/scope.js";
import type { PromotionPreview } from "../src/review/promotion.js";
import type { ReportFindingRecord } from "./types.js";
import type { ReviewDraftView, ReviewVerdict, StagedDecisionView } from "./review-types.js";
import { renderPromotionPanel } from "./promotion-panel.js";

export const CONFIRM_DEFECT_LABEL = "✓ Confirm defect";
export const NOT_DEFECT_LABEL = "✕ Not a defect";
export const UNDO_LABEL = "Undo decision";

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

function verdictLabel(verdict: ReviewVerdict): string {
  return verdict === "confirmed_defect" ? "Confirmed defect" : "Not a defect";
}

function scopeSummary(scope: DecisionScope): string {
  if (scope.kind === "exact") {
    return `Exact scope: ${scope.target.canonicalTarget} (${scope.detector.id}@${scope.detector.version})`;
  }
  return `Reviewed policy: ${scope.policyId} (expires ${scope.expiresAt})`;
}

function renderScopeEditor(
  finding: ReportFindingRecord,
  staged: StagedDecisionView | undefined,
): string {
  const scopeKind = staged?.scope.kind ?? "exact";
  const isPolicy = scopeKind === "reviewed-policy";
  const policyScope = isPolicy && staged?.scope.kind === "reviewed-policy" ? staged.scope : undefined;
  const scopeText =
    staged === undefined
      ? `Exact scope: ${finding.target.canonical} (${finding.detector.id}@${finding.detector.version})`
      : scopeSummary(staged.scope);

  return `
    <details class="scope-editor" data-scope-editor="true">
      <summary>Decision scope</summary>
      <p data-scope-kind="${escapeHtml(scopeKind)}">${escapeHtml(scopeText)}</p>
      <label>
        <input
          type="checkbox"
          data-review-field="use-policy-scope"
          ${isPolicy ? "checked" : ""}
        />
        Use broader reviewed-policy scope
      </label>
      <div class="policy-scope-fields" data-policy-scope-fields="${isPolicy ? "visible" : "hidden"}" ${isPolicy ? "" : "hidden"}>
        <p class="policy-warning" data-policy-warning="true" role="alert">
          Warning: reviewed-policy scope affects multiple findings and cannot be promoted to blocking contracts.
        </p>
        <label for="policy-id-${escapeHtml(finding.id)}">Policy ID</label>
        <input
          id="policy-id-${escapeHtml(finding.id)}"
          data-review-field="policy-id"
          value="${escapeHtml(policyScope?.policyId ?? `policy-${finding.id}`)}"
        />
        <label for="policy-expires-${escapeHtml(finding.id)}">Expiry (ISO-8601)</label>
        <input
          id="policy-expires-${escapeHtml(finding.id)}"
          data-review-field="policy-expires"
          value="${escapeHtml(policyScope?.expiresAt ?? "2027-12-31T23:59:59.000Z")}"
        />
        <label for="policy-justification-${escapeHtml(finding.id)}">Justification</label>
        <textarea
          id="policy-justification-${escapeHtml(finding.id)}"
          data-review-field="policy-justification"
        >${escapeHtml(policyScope?.justification ?? "")}</textarea>
        <p data-impact-preview="true">
          Impact preview: broader scope may match additional findings with the same detector and context predicates.
        </p>
      </div>
    </details>
  `;
}

export function renderReviewPanel(input: {
  finding: ReportFindingRecord;
  draft: ReviewDraftView;
  promotionPreview?: PromotionPreview;
}): string {
  const { finding, draft, promotionPreview } = input;
  const staged = draft.decisions.find((entry) => entry.findingId === finding.id);
  const notes = draft.notes[finding.id] ?? "";
  const canUndo = (draft.undoStacks[finding.id]?.length ?? 0) > 0;
  const isAdvisory = finding.lane === "advisory";

  const confirmationState =
    staged === undefined
      ? ""
      : `
        <p
          class="review-confirmation"
          data-review-confirmation="true"
          data-review-verdict="${escapeHtml(staged.verdict)}"
          aria-live="polite"
        >
          Decision: <strong>${escapeHtml(verdictLabel(staged.verdict))}</strong>
          ${staged.reason === undefined ? "" : ` — ${escapeHtml(staged.reason)}`}
        </p>
        ${
          staged.verdict === "confirmed_defect"
            ? `
              <p
                class="non-blocking-notice"
                data-non-blocking-notice="true"
                role="status"
              >
                Confirmed advisory — non-blocking until exact executable-contract promotion completes.
              </p>
            `
            : ""
        }
      `;

  const reasonField = `
    <label for="review-reason-${escapeHtml(finding.id)}">
      Reason ${isAdvisory ? "(recommended for advisory findings)" : "(optional)"}
    </label>
    <textarea
      id="review-reason-${escapeHtml(finding.id)}"
      data-review-field="reason"
      aria-describedby="review-reason-help-${escapeHtml(finding.id)}"
    >${escapeHtml(staged?.reason ?? "")}</textarea>
    <span id="review-reason-help-${escapeHtml(finding.id)}" class="help-text">
      Required when using reviewed-policy scope for not a defect decisions.
    </span>
  `;

  const notesField = `
    <label for="review-notes-${escapeHtml(finding.id)}">Reviewer notes</label>
    <textarea
      id="review-notes-${escapeHtml(finding.id)}"
      data-review-field="notes"
    >${escapeHtml(notes)}</textarea>
  `;

  return `
    <section
      class="review-panel"
      data-report-section="review"
      data-review-panel="true"
      data-finding-id="${escapeHtml(finding.id)}"
      data-draft-revision="${String(draft.revision)}"
      aria-labelledby="review-panel-heading"
    >
      <h2 id="review-panel-heading">Review decision</h2>
      ${confirmationState}
      <div class="review-actions" role="group" aria-label="Review verdict actions">
        <button
          type="button"
          data-review-action="confirm-defect"
          aria-label="${escapeHtml(CONFIRM_DEFECT_LABEL)}"
          accesskey="c"
        >${escapeHtml(CONFIRM_DEFECT_LABEL)}</button>
        <button
          type="button"
          data-review-action="not-defect"
          aria-label="${escapeHtml(NOT_DEFECT_LABEL)}"
          accesskey="n"
        >${escapeHtml(NOT_DEFECT_LABEL)}</button>
        <button
          type="button"
          data-review-action="undo"
          aria-label="${escapeHtml(UNDO_LABEL)}"
          accesskey="u"
          ${canUndo ? "" : "disabled"}
        >${escapeHtml(UNDO_LABEL)}</button>
      </div>
      ${reasonField}
      ${notesField}
      ${renderScopeEditor(finding, staged)}
      ${
        staged?.verdict === "confirmed_defect"
          ? renderPromotionPanel({
              findingId: finding.id,
              preview: promotionPreview,
              ...(staged.promotion?.status === "staged" ? { promotionStatus: "staged" } : {}),
            })
          : ""
      }
    </section>
  `;
}
