// HTML rendering with theme support, font loading, and image handling
// Procedural style: Functions, not classes

interface RendererConfig {
  readingTheme: "light" | "sepia" | "dark" | "night" | "high-contrast";
  readingFont:
    | "literata"
    | "crimson"
    | "source-serif"
    | "eb-garamond"
    | "libertinus"
    | "noto-serif"
    | "charis-sil"
    | "ibm-plex";
  fontSize: number;
  lineHeight: number;
  marginWidth: number;
  textAlign: "left" | "justify";
  columnCount: 1 | 2;
}

// ============================================================
// Main Render Function
// ============================================================

export async function renderHTMLDocument(
  doc: HTMLDocument,
  container: HTMLElement,
  config: RendererConfig,
): Promise<void> {
  // Apply theme
  applyHTMLTheme(container, config.readingTheme);

  // Apply typography settings
  applyHTMLTypography(container, config);

  // Inject custom styles for reader
  injectHTMLReaderStyles(container);

  // Handle embedded fonts
  await loadEmbeddedHTMLFonts(doc, container);

  // Handle images
  processHTMLImages(doc, container);

  // Clear container and append content
  container.innerHTML = "";
  container.appendChild(doc.body);

  // Apply column layout
  applyHTMLColumnLayout(container, config.columnCount);
}

// ============================================================
// Theme Application
// ============================================================

function applyHTMLTheme(container: HTMLElement, theme: string): void {
  const readingThemes: Record<string, Record<string, string>> = {
    light: {
      "--bg-primary": "#ffffff",
      "--text-primary": "#1a1a1a",
      "--text-secondary": "#666666",
      "--accent": "#0066cc",
    },
    sepia: {
      "--bg-primary": "#f4ecd8",
      "--text-primary": "#5f4b32",
      "--text-secondary": "#8b7355",
      "--accent": "#8b4513",
    },
    dark: {
      "--bg-primary": "#1a1b26",
      "--text-primary": "#c0caf5",
      "--text-secondary": "#565f89",
      "--accent": "#7aa2f7",
    },
    night: {
      "--bg-primary": "#0d1117",
      "--text-primary": "#c9d1d9",
      "--text-secondary": "#8b949e",
      "--accent": "#58a6ff",
    },
    "high-contrast": {
      "--bg-primary": "#000000",
      "--text-primary": "#ffffff",
      "--text-secondary": "#cccccc",
      "--accent": "#ffff00",
    },
  };

  const themeConfig = readingThemes[theme] || readingThemes["dark"];

  for (const [key, value] of Object.entries(themeConfig)) {
    container.style.setProperty(key, value);
  }
}

function applyHTMLTypography(
  container: HTMLElement,
  config: RendererConfig,
): void {
  const style = document.createElement("style");
  const fontStack = getFontStack(config.readingFont);

  style.textContent = `
    .ebook-content {
      font-family: ${fontStack};
      font-size: ${config.fontSize}px;
      line-height: ${config.lineHeight};
      text-align: ${config.textAlign};
      padding: 0 ${config.marginWidth}px;
      max-width: 100%;
      overflow-wrap: break-word;
    }

    .ebook-content p {
      margin-bottom: 1em;
      text-indent: ${config.textAlign === "justify" ? "1.5em" : "0"};
    }

    .ebook-content img {
      max-width: 100%;
      height: auto;
      display: block;
      margin: 1em auto;
    }

    .ebook-content a {
      color: var(--accent);
      text-decoration: underline;
    }

    .ebook-content a:active {
      color: var(--text-secondary);
    }
  `;

  container.appendChild(style);
}

function injectHTMLReaderStyles(container: HTMLElement): void {
  container.setAttribute("role", "main");
  container.setAttribute("aria-label", "Book content");
}

async function loadEmbeddedHTMLFonts(
  doc: HTMLDocument,
  container: HTMLElement,
): Promise<void> {
  const styleSheets = doc.querySelectorAll("style");

  for (const sheet of styleSheets) {
    const fontFaceRegex = /@font-face\s*{([^}]+)}/g;
    const matches = sheet.textContent?.matchAll(fontFaceRegex) || [];

    for (const match of matches) {
      const fontFace = match[1];
      const urlMatch = /url\(['"]?([^'")]+)['"]?\)/.exec(fontFace);

      if (urlMatch) {
        const fontUrl = urlMatch[1];
        await loadHTMLFont(fontUrl, container);
      }
    }
  }
}

async function loadHTMLFont(
  fontUrl: string,
  container: HTMLElement,
): Promise<void> {
  const loadedFonts = container.dataset.loadedFonts
    ? JSON.parse(container.dataset.loadedFonts)
    : [];

  if (loadedFonts.includes(fontUrl)) return;

  try {
    const fontFace = new FontFace("custom-font", `url(${fontUrl})`);
    await fontFace.load();
    document.fonts.add(fontFace);

    loadedFonts.push(fontUrl);
    container.dataset.loadedFonts = JSON.stringify(loadedFonts);
  } catch (error) {
    console.error("Failed to load font:", fontUrl, error);
  }
}

function processHTMLImages(doc: HTMLDocument): void {
  const images = doc.querySelectorAll("img");

  images.forEach((img) => {
    img.setAttribute("loading", "lazy");

    if (!img.alt) {
      img.alt = "Image from book";
    }

    img.style.cursor = "pointer";
    img.addEventListener("click", () => {
      showImageFullscreen(img.src);
    });
  });
}

function showImageFullscreen(src: string): void {
  const modal = document.createElement("div");
  modal.className =
    "fixed inset-0 bg-black bg-opacity-90 flex items-center justify-center z-50";
  modal.onclick = () => modal.remove();

  const img = document.createElement("img");
  img.src = src;
  img.className = "max-w-full max-h-full object-contain";

  modal.appendChild(img);
  document.body.appendChild(modal);
}

function applyHTMLColumnLayout(
  container: HTMLElement,
  columnCount: number,
): void {
  if (columnCount === 2) {
    container.style.columnCount = "2";
    container.style.columnGap = "20px";
    container.style.columnRule = "1px solid var(--text-secondary)";
  } else {
    container.style.columnCount = "auto";
  }
}

function getFontStack(font: string): string {
  const stacks: Record<string, string> = {
    literata: '"Literata", serif',
    crimson: '"Crimson Text", serif',
    "source-serif": '"Source Serif 4", serif',
    "eb-garamond": '"EB Garamond", serif',
    libertinus: '"Libertinus Serif", serif',
    "noto-serif": '"Noto Serif", serif',
    "charis-sil": '"Charis SIL", serif',
    "ibm-plex": '"IBM Plex Serif", serif',
  };

  return stacks[font] || stacks["literata"];
}
