import type { CheckImage, CheckResult, CheckStatus, EdmCheck } from "../types";
import { ALLOWED_IMAGE_EXT, extOf, fileNameOf, getImages, isHttps } from "../htmlUtils";

const loadImage = (src: string): Promise<boolean> => {
  if (typeof window === "undefined") return Promise.resolve(false);
  return new Promise<boolean>((resolve) => {
    const img = new window.Image();
    img.onload = () => resolve(true);
    img.onerror = () => resolve(false);
    img.src = src;
    setTimeout(() => resolve(false), 5000);
  });
};

export const fileNameCheck: EdmCheck = {
  id: "fileName",
  label: "File name",
  description:
    "Image naming convention (no spaces — use underscores or hyphens), allowed extensions (jpg/png only), https URLs, and load check for every image.",
  run: async ({ doc }): Promise<CheckResult> => {
    const imgs = getImages(doc).filter((i) => i.src);

    const imageChecks = await Promise.all(
      imgs.map(async (i): Promise<CheckImage> => {
        const ext = extOf(i.src);
        const name = fileNameOf(i.src);
        const hasSpaces = /[\s]|%20/i.test(name);
        const validExt = ALLOWED_IMAGE_EXT.includes(ext);
        const secure = isHttps(i.src);
        const broken = secure ? !(await loadImage(i.src)) : false;
        return {
          src: i.src,
          alt: i.alt,
          ext,
          hasSpaces,
          broken,
          ok: validExt && secure && !hasSpaces && !broken,
        };
      }),
    );

    const flaggedBroken = imageChecks.filter((i) => i.broken);
    const flaggedSpaces = imageChecks.filter((i) => i.hasSpaces);
    const flaggedExt = imageChecks.filter((i) => !ALLOWED_IMAGE_EXT.includes(i.ext));
    const flaggedHttps = imageChecks.filter((i) => ALLOWED_IMAGE_EXT.includes(i.ext) && !isHttps(i.src));

    const counts = imageChecks.reduce<Record<string, number>>((acc, i) => {
      const key = i.ext || "(none)";
      acc[key] = (acc[key] ?? 0) + 1;
      return acc;
    }, {});
    const summary = Object.entries(counts)
      .map(([ext, n]) => `${ext} ×${n}${ALLOWED_IMAGE_EXT.includes(ext) ? "" : " ⚠"}`)
      .join(", ");

    let status: CheckStatus = "pass";
    const messages: string[] = [
      imageChecks.length
        ? `${imageChecks.length} image${imageChecks.length === 1 ? "" : "s"}: ${summary}`
        : "No images found.",
    ];

    if (flaggedBroken.length) {
      messages.push(
        `${flaggedBroken.length} image${flaggedBroken.length === 1 ? "" : "s"} failed to load — check the URL or asset storage.`,
      );
      status = "warning";
    }
    if (flaggedSpaces.length) {
      messages.push(
        `${flaggedSpaces.length} filename${flaggedSpaces.length === 1 ? "" : "s"} contain spaces — rename using underscores or hyphens.`,
      );
      if (status === "pass") status = "warning";
    }
    if (flaggedExt.length) {
      messages.push(`${flaggedExt.length} image(s) use a non-allowed extension (only jpg/png allowed).`);
      if (status === "pass") status = "warning";
    }
    if (flaggedHttps.length) {
      messages.push(`${flaggedHttps.length} image(s) are not loaded over https.`);
      if (status === "pass") status = "warning";
    }

    return { status, messages, images: imageChecks };
  },
};
