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

export const sendgridCheck: EdmCheck = {
  id: "sendgrid",
  label: "SendGrid",
  description: "SendGrid {{ }} substitution syntax + variable list (e.g. {{full_name}}).",
  run: ({ htmlContent }): CheckResult => {
    const variables = extractHandlebars(htmlContent);
    const messages: string[] = [];
    let status: CheckStatus = "pass";

    // Balanced delimiters: each valid tag has one "{{" and one "}}".
    const open = (htmlContent.match(/\{\{/g) ?? []).length;
    const close = (htmlContent.match(/\}\}/g) ?? []).length;
    if (open !== close) {
      messages.push(`Unbalanced {{ }} delimiters (${open} "{{" vs ${close} "}}").`);
      status = "warning";
    }

    // Empty tags.
    if (/\{\{\s*\}\}/.test(htmlContent)) {
      messages.push(`Found an empty tag ("{{}}").`);
      status = "warning";
    }

    // Mismatched: {{var} — double-open, single-close.
    const doubleOpenSingleClose: string[] = [];
    const doRe = /\{\{([^{}]+)\}(?!\})/g;
    let doM: RegExpExecArray | null;
    while ((doM = doRe.exec(htmlContent)) !== null) {
      doubleOpenSingleClose.push(doM[0].slice(0, 50));
    }
    if (doubleOpenSingleClose.length) {
      const examples = doubleOpenSingleClose.slice(0, 3).map((s) => `"${s}"`).join(", ");
      messages.push(`Mismatched braces — double-open, single-close (${examples}). Did you mean {{ … }}?`);
      status = "warning";
    }

    // Mismatched: {var}} — single-open, double-close.
    const singleOpenDoubleClose: string[] = [];
    const soRe = /(?<!\{)\{([^{}]+)\}\}/g;
    let soM: RegExpExecArray | null;
    while ((soM = soRe.exec(htmlContent)) !== null) {
      singleOpenDoubleClose.push(soM[0].slice(0, 50));
    }
    if (singleOpenDoubleClose.length) {
      const examples = singleOpenDoubleClose.slice(0, 3).map((s) => `"${s}"`).join(", ");
      messages.push(`Mismatched braces — single-open, double-close (${examples}). Did you mean {{ … }}?`);
      status = "warning";
    }

    // Single-brace variables {var} that look like Handlebars names but are
    // missing the outer brace pair. Skips CSS-like content (colons, semicolons).
    const singleBraceVars: string[] = [];
    const sbRe = /(?<!\{)\{([a-z_#/][a-z0-9_./ ]*)\}(?!\})/gi;
    let sbM: RegExpExecArray | null;
    while ((sbM = sbRe.exec(htmlContent)) !== null) {
      const inner = sbM[1].trim();
      if (/[:;%@]/.test(inner)) continue; // skip CSS rules
      singleBraceVars.push(sbM[0].slice(0, 50));
    }
    if (singleBraceVars.length) {
      const examples = singleBraceVars.slice(0, 3).map((s) => `"${s}"`).join(", ");
      messages.push(
        `Possible single-brace variable${singleBraceVars.length === 1 ? "" : "s"} found (${examples}). Did you mean {{ … }}?`,
      );
      if (status === "pass") status = "warning";
    }

    // Block helpers ({{#if}} … {{/if}}) must pair up.
    const opens = variables.filter((v) => /^#/.test(v.name)).reduce((n, v) => n + v.count, 0);
    const closes = variables.filter((v) => /^\//.test(v.name)).reduce((n, v) => n + v.count, 0);
    if (opens !== closes) {
      messages.push(`Unbalanced block helpers: ${opens} {{#…}} vs ${closes} {{/…}}.`);
      if (status !== "fail") status = "warning";
    }

    messages.unshift(
      variables.length
        ? `Found ${variables.length} SendGrid variable${variables.length === 1 ? "" : "s"} (e.g. {{full_name}}); syntax ${status === "pass" ? "looks valid" : "has issues"}.`
        : "No SendGrid {{ }} variables found.",
    );

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