// What the sidebar and the meta box show, decided without the DOM so it can be tested: issues grouped by WCAG
// criterion and numbered in stored order (the preview badge shows the same number), and the Show in preview link.
import type { Impact, Issue, PageResult } from "@income-factory/core";

export interface NumberedIssue {
  issue: Issue;
  /** 1-based position in the stored result; the preview highlight shows the same number. */
  number: number;
}

export interface IssueGroup {
  id: string;
  /** Criterion number such as "1.1.1"; empty for the best-practice group, which the UI names itself. */
  sc: string;
  name: string;
  level: string;
  url?: string;
  issues: NumberedIssue[];
}

export const BEST_PRACTICE = "best-practice";

const IMPACT_RANK: Record<Impact, number> = { critical: 0, serious: 1, moderate: 2, minor: 3 };

/** "1.4.12" sorts after "1.4.3". */
const scOrder = (sc: string) => sc.split(".").map((n) => n.padStart(3, "0")).join(".");

/**
 * Issues grouped by WCAG success criterion in WCAG order, rules without a criterion last. An issue mapped to two
 * criteria shows under both. Inside a group the most severe come first.
 */
export function groupByCriterion(result: Pick<PageResult, "issues">): IssueGroup[] {
  const groups = new Map<string, IssueGroup>();
  result.issues.forEach((issue, index) => {
    const numbered = { issue, number: index + 1 };
    const targets = issue.criteria.length > 0 ? issue.criteria : [null];
    for (const c of targets) {
      const id = c ? c.sc : BEST_PRACTICE;
      let group = groups.get(id);
      if (!group) {
        group = c ? { id, sc: c.sc, name: c.name, level: c.level, url: c.url, issues: [] } : { id, sc: "", name: "", level: BEST_PRACTICE, issues: [] };
        groups.set(id, group);
      }
      group.issues.push(numbered);
    }
  });
  const list = [...groups.values()];
  for (const g of list) g.issues.sort((a, b) => IMPACT_RANK[a.issue.impact] - IMPACT_RANK[b.issue.impact] || a.number - b.number);
  return list.sort((a, b) => (a.id === BEST_PRACTICE ? 1 : b.id === BEST_PRACTICE ? -1 : scOrder(a.sc).localeCompare(scOrder(b.sc))));
}

/** The preview URL that outlines one issue: the server checks the nonce and the user's rights before it does. */
export function highlightUrl(previewUrl: string, key: string, nonce: string, base: string = window.location.href): string {
  const url = new URL(previewUrl, base);
  url.searchParams.set("waysill_highlight", key);
  url.searchParams.set("waysill_nonce", nonce);
  return url.toString();
}
