import type { CheckLink, CheckResult, CheckStatus, EdmCheck } from "../types";
import {
  getAnchors,
  getImages,
  isHttps,
  isLocalhost,
  isMergeTag,
  isRelative,
} from "../htmlUtils";

export const pathCheck: EdmCheck = {
  id: "path",
  label: "URL / path check",
  description: "Flags localhost, non-https and relative paths; lists redirect URLs to preview.",
  run: ({ doc }): CheckResult => {
    // Every URL-bearing reference (anchors + images).
    const refs: { href: string; from: string }[] = [
      ...getAnchors(doc).map((a) => ({ href: a.href, from: "link" })),
      ...getImages(doc).map((i) => ({ href: i.src, from: "image" })),
    ].filter((r) => r.href && !isMergeTag(r.href) && !/^(mailto:|tel:|#)/i.test(r.href));

    const bad: CheckLink[] = [];
    const messages: string[] = [];
    let status: CheckStatus = "pass";
    const escalate = (_s: CheckStatus) => {
      status = "warning";
    };

    let localhost = 0;
    let insecure = 0;
    let relative = 0;
    for (const r of refs) {
      if (isLocalhost(r.href)) {
        localhost++;
        bad.push({ label: `localhost (${r.from})`, href: r.href, present: true, isMergeTag: false });
        escalate("fail");
      } else if (/^http:\/\//i.test(r.href)) {
        insecure++;
        bad.push({ label: `http, not https (${r.from})`, href: r.href, present: true, isMergeTag: false });
        escalate("fail");
      } else if (isRelative(r.href)) {
        relative++;
        bad.push({ label: `relative path (${r.from})`, href: r.href, present: true, isMergeTag: false });
        escalate("warning");
      }
    }

    if (localhost) messages.push(`${localhost} localhost URL(s) — must be a public https URL.`);
    if (insecure) messages.push(`${insecure} non-https URL(s).`);
    if (relative) messages.push(`${relative} relative/scheme-less path(s) — likely won't resolve in email.`);
    if (!bad.length) messages.push("All links/images use absolute https URLs.");

    // Also surface the deduped real redirect URLs so QA can spot-check.
    const redirectSet = new Map<string, CheckLink>();
    for (const a of getAnchors(doc)) {
      if (a.href && isHttps(a.href) && !redirectSet.has(a.href)) {
        redirectSet.set(a.href, { label: a.text || "(link)", href: a.href, present: true, isMergeTag: false });
      }
    }

    return { status, messages, links: [...bad, ...redirectSet.values()] };
  },
};
