import type { CheckLink, CheckResult, CheckStatus, EdmCheck } from "../types";
import { extractVariables, findAnchorByText, isMergeTag } from "../htmlUtils";

// The four footer items every Karma EDM should carry. `url` items hold a real
// link (openable); `mergetag` items must hold a specific Mailchimp merge tag.
const FOOTER_ITEMS: {
  label: string;
  re: RegExp;
  kind: "url" | "mergetag";
  expectedTag?: string;
  missingSeverity: CheckStatus;
}[] = [
  { label: "View in Browser", re: /view in browser/i, kind: "url", missingSeverity: "warning" },
  { label: "View Online", re: /view online/i, kind: "url", missingSeverity: "warning" },
  { label: "Go to our Website", re: /go to our website/i, kind: "url", missingSeverity: "warning" },
  { label: "Update Preferences", re: /update preferences/i, kind: "mergetag", expectedTag: "*|UPDATE_PROFILE|*", missingSeverity: "fail" },
  { label: "Unsubscribe", re: /unsubscribe/i, kind: "mergetag", expectedTag: "*|UNSUB|*", missingSeverity: "fail" },
];

export const mailchimpCheck: EdmCheck = {
  id: "mailchimp",
  label: "Mailchimp",
  description: "Merge variables, preview text + preheader, and footer links (View in Browser, Website, Update Preferences, Unsubscribe).",
  run: ({ htmlContent, doc }): CheckResult => {
    const variables = extractVariables(htmlContent);
    const messages: string[] = [];
    const links: CheckLink[] = [];
    let status: CheckStatus = "pass";
    const escalate = (_s: CheckStatus) => {
      status = "warning";
    };

    // Preview text + hidden preheader span (both live at the top of the body).
    const hasPreviewVar = /\*\|MC_PREVIEW_TEXT\|\*/.test(htmlContent);
    const previewSpan = doc.querySelector(".mcnPreviewText");
    const preheaderSpan = doc.querySelector(".preheader");
    if (!hasPreviewVar) {
      messages.push("Missing *|MC_PREVIEW_TEXT|* preview text.");
      escalate("warning");
    } else if (!previewSpan) {
      messages.push("*|MC_PREVIEW_TEXT|* is not inside a .mcnPreviewText span.");
      escalate("warning");
    } else {
      messages.push("Preview text (*|MC_PREVIEW_TEXT|*) present.");
    }
    if (!preheaderSpan) {
      messages.push("Missing hidden .preheader span.");
      escalate("warning");
    } else {
      messages.push("Preheader span present.");
    }

    for (const item of FOOTER_ITEMS) {
      const anchor = findAnchorByText(doc, item.re);
      if (!anchor) {
        messages.push(`Missing "${item.label}".`);
        links.push({ label: item.label, href: "", present: false, isMergeTag: false });
        escalate(item.missingSeverity);
        continue;
      }
      const tag = isMergeTag(anchor.href);
      links.push({ label: item.label, href: anchor.href, present: true, isMergeTag: tag });

      if (item.kind === "mergetag" && anchor.href !== item.expectedTag) {
        messages.push(
          `"${item.label}" should link to ${item.expectedTag} but is "${anchor.href || "(empty)"}".`,
        );
        escalate("fail");
      } else if (item.kind === "url" && (!anchor.href || tag)) {
        messages.push(`"${item.label}" has no real URL.`);
        escalate("warning");
      }
    }

    messages.unshift(
      variables.length
        ? `Found ${variables.length} merge variable${variables.length === 1 ? "" : "s"}.`
        : "No merge variables found.",
    );

    return { status, messages, links, variables };
  },
};
