import type { CheckResult, CheckStatus, EdmCheck } from "../types";

// Tags that must be explicitly closed in email HTML
const CHECKED_TAGS = [
  "html", "head", "body",
  "div", "span", "p", "center", "font",
  "table", "tbody", "thead", "tfoot", "tr", "td", "th",
  "a", "strong", "em", "b", "i", "u",
  "h1", "h2", "h3", "h4", "h5", "h6",
  "style", "title",
];

// Tags that are not supported / dangerous in email clients
const BAD_EMAIL_TAGS = ["script", "form", "iframe", "object", "embed"];

export const htmlCheck: EdmCheck = {
  id: "html",
  label: "HTML check",
  description: "Basic structure: DOCTYPE, unclosed tags, and email-unsafe elements (script, form, iframe).",
  run: ({ htmlContent }): CheckResult => {
    let status: CheckStatus = "pass";
    const messages: string[] = [];

    if (!htmlContent.trim()) {
      return { status: "warning", messages: ["No HTML content to validate."] };
    }

    // DOCTYPE
    if (!/<!doctype\s+html/i.test(htmlContent)) {
      messages.push("Missing <!DOCTYPE html> declaration.");
      status = "warning";
    }

    // Email-unsafe tags
    for (const tag of BAD_EMAIL_TAGS) {
      if (new RegExp(`<${tag}[\\s>/]`, "i").test(htmlContent)) {
        messages.push(`Found <${tag}> — not supported in email clients.`);
        if (status === "pass") status = "warning";
      }
    }

    const lineAt = (index: number) =>
      htmlContent.slice(0, index).split("\n").length;
    const unclosed: string[] = [];
    for (const tag of CHECKED_TAGS) {
      const re = new RegExp(
        `<\\s*(/?)\\s*${tag}(?:\\s[^>]*)?(?<!/)>`,
        "gi",
      );
      const openLines: number[] = [];
      const orphanCloseLines: number[] = [];
      let m: RegExpExecArray | null;
      while ((m = re.exec(htmlContent)) !== null) {
        if (m[1] === "/") {
          if (openLines.length) openLines.pop();
          else orphanCloseLines.push(lineAt(m.index));
        } else {
          openLines.push(lineAt(m.index));
        }
      }
      for (const line of openLines) {
        unclosed.push(`<${tag}> not closed (line ${line})`);
      }
      for (const line of orphanCloseLines) {
        unclosed.push(`</${tag}> has no opening tag (line ${line})`);
      }
    }
    if (unclosed.length) {
      const shown = unclosed.slice(0, 6);
      const extra = unclosed.length - shown.length;
      messages.push(
        `Unclosed tags: ${shown.join("; ")}${extra > 0 ? ` + ${extra} more` : ""}.`,
      );
      if (status === "pass") status = "warning";
    }

    if (messages.length === 0) {
      messages.push("No HTML issues detected.");
    }

    return { status, messages };
  },
};
