// HTML Parser - Wraps standalone HTML files
// Procedural style: Functions, not classes

// ============================================================
// Main Parse Function
// ============================================================

export async function parseHTML(htmlBlob: Blob): Promise<EbookCIF> {
  const htmlContent = await htmlBlob.text();

  const metadata = extractHTMLMetadata(htmlBlob, htmlContent);
  const toc = createHTMLTOC(htmlContent);
  const spine = createHTMLSpine(htmlContent);
  const resources = await extractHTMLResources(htmlBlob, htmlContent);

  const totalCharacters = stripHTML(htmlContent).length;
  const pageBreaks = generatePageBreaks(totalCharacters);

  return {
    metadata,
    toc,
    spine,
    resources,
    locations: {
      totalCharacters,
      pageBreaks,
    },
  };
}

// ============================================================
// Helper Functions
// ============================================================

function extractHTMLMetadata(
  htmlBlob: Blob,
  htmlContent: string,
): EbookCIF["metadata"] {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlContent, "text/html");

  const title =
    doc.querySelector("title")?.textContent ||
    htmlBlob.name.replace(/\.(html?|htm)$/i, "");

  const metaAuthor = doc
    .querySelector('meta[name="author"]')
    ?.getAttribute("content");
  const metaLang = doc.querySelector("html")?.getAttribute("lang") || "en";

  return {
    title,
    author: metaAuthor || "Unknown",
    language: metaLang,
  };
}

function createHTMLTOC(htmlContent: string): EbookCIF["toc"] {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlContent, "text/html");

  const toc: EbookCIF["toc"] = [];

  // Try to find headings
  const headings = doc.querySelectorAll("h1, h2, h3");
  let headingIndex = 0;

  headings.forEach((heading) => {
    toc.push({
      id: `heading-${headingIndex}`,
      title: heading.textContent || "",
      href: `#${heading.id || `heading-${headingIndex}`}`,
      children: [],
    });

    headingIndex++;
  });

  // If no headings, create single entry
  if (toc.length === 0) {
    toc.push({
      id: "full-document",
      title: "Full Document",
      href: "#full-document",
      children: [],
    });
  }

  return toc;
}

function createHTMLSpine(htmlContent: string): EbookCIF["spine"] {
  return [
    {
      id: "full-document",
      type: "html",
      content: htmlContent,
      index: 0,
    },
  ];
}

async function extractHTMLResources(
  htmlBlob: Blob,
  htmlContent: string,
): Promise<Map<string, Blob>> {
  const resources = new Map<string, Blob>();
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlContent, "text/html");

  // Extract images
  const images = doc.querySelectorAll("img[src]");

  for (const img of Array.from(images)) {
    const src = img.getAttribute("src");
    if (!src) continue;

    // Try to resolve relative URLs
    if (src.startsWith("data:")) {
      // Data URI - extract blob
      const match = src.match(/^data:([^;]+);base64,(.+)$/);
      if (match) {
        const mimeType = match[1];
        const base64 = match[2];
        const byteString = atob(base64);
        const byteArray = new Uint8Array(byteString.length);

        for (let i = 0; i < byteString.length; i++) {
          byteArray[i] = byteString.charCodeAt(i);
        }

        const blob = new Blob([byteArray], { type: mimeType });
        resources.set(src, blob);
      }
    }
    // External resources would need to be fetched
    // For now, skip them (browser will load them naturally)
  }

  return resources;
}

function stripHTML(html: string): string {
  const div = document.createElement("div");
  div.innerHTML = html;
  return div.textContent || "";
}

// ============================================================
// Metadata Quick Extract
// ============================================================

export async function getHTMLMetadata(
  htmlBlob: Blob,
): Promise<Partial<EbookCIF["metadata"]>> {
  const htmlContent = await htmlBlob.text();
  return extractHTMLMetadata(htmlBlob, htmlContent);
}
