"use client";

import { Fragment, useEffect, useRef, useState } from "react";
import { Lab1ConfidenceChat } from "~/components/labs/Lab1ConfidenceChat";
import { Lab1NetronPanel } from "~/components/labs/Lab1NetronPanel";
import { Lab3TerminalFrame } from "~/components/labs/Lab3TerminalFrame";
import { Objective5Chat } from "~/components/labs/Objective5Chat";
import { QuantizationGridExplorer } from "~/components/labs/QuantizationGridExplorer";
import { QuantizationExplorer } from "~/components/labs/QuantizationExplorer";
import { TokenizerPlaygroundEmbed } from "~/components/labs/TokenizerPlaygroundEmbed";

type LabContentProps = {
  className: string;
  html: string;
};

const cliLanguagePattern =
  /\b(language-(bash|sh|shell|zsh|console|terminal)|bash|shell|zsh)\b/i;
const cliCommandPattern =
  /(^|\n)\s*(\$|sudo\s|git\s|python3?\s|pip\s|npm\s|pnpm\s|yarn\s|llama-|ollama\s|curl\s|wget\s|apt\s|cd\s|ls\s|cat\s|cp\s|mv\s|chmod\s|make\s)/i;
const promptLanguagePattern =
  /\b(language-(text|plaintext|md|markdown)|text|plaintext|markdown)\b/i;
const promptSignalPattern =
  /\b(you are|guidelines|follow these|example|when provided|system prompt|tasked with)\b/i;

type ParsedSetting = {
  key: string;
  value: string;
};

type ZoomedImageState = {
  src: string;
  alt: string;
};

const quantizationExplorerToken = "<div data-quantization-explorer></div>";
const quantizationGridExplorerToken =
  "<div data-quantization-grid-explorer></div>";
const objective5ChatToken = "<div data-objective5-chat></div>";
const lab3TerminalToken = "<div data-lab3-terminal></div>";
const lab1ConfidenceToken = "<div data-lab1-confidence></div>";
const lab1NetronToken = "<div data-lab1-netron-panel></div>";
const tokenizerPlaygroundToken = "<div data-tokenizer-playground></div>";

function looksLikeCliCommand(commandText: string, className: string) {
  if (cliLanguagePattern.test(className)) return true;
  return (
    cliCommandPattern.test(commandText) || /--[a-z0-9-]+/i.test(commandText)
  );
}

function looksLikePromptTextBlock(text: string, className: string) {
  if (looksLikeCliCommand(text, className)) return false;

  const normalizedText = text.trim();
  if (!normalizedText) return false;

  const lineCount = normalizedText.split("\n").length;
  if (promptLanguagePattern.test(className) && normalizedText.length > 80)
    return true;
  if (lineCount >= 4 && promptSignalPattern.test(normalizedText)) return true;
  if (lineCount >= 6 && /(^|\n)\s*[*-]\s+/.test(normalizedText)) return true;
  return false;
}

function escapeRegex(value: string) {
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function escapeHtml(value: string) {
  return value
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#39;");
}

function parseSettingListItem(item: HTMLLIElement): ParsedSetting | null {
  const keyElement = item.querySelector("code");
  if (!keyElement) return null;

  const key = (keyElement.textContent ?? "").replace(/\s+/g, " ").trim();
  if (!key || key.length > 40) return null;

  const text = (item.textContent ?? "").replace(/\s+/g, " ").trim();
  const match = new RegExp(
    `^${escapeRegex(key)}\\s*(?:-|–|—|:|=)\\s*(.+)$`,
  ).exec(text);
  if (!match) return null;

  const value = (match[1] ?? "").replace(/\s+/g, " ").trim();
  if (!value || value.length > 36) return null;
  if (/[.;]/.test(value) && value.length > 16) return null;

  return { key, value };
}

function enhanceSettingsLists(root: HTMLElement) {
  const lists = root.querySelectorAll<HTMLUListElement>("ul");

  for (const list of lists) {
    if (list.dataset.settingsEnhanced === "true") continue;

    const items = Array.from(list.children).filter(
      (node): node is HTMLLIElement => {
        return node.tagName === "LI";
      },
    );
    if (items.length < 2) continue;

    const parsedItems = items.map((item) => parseSettingListItem(item));
    if (parsedItems.some((parsedItem) => parsedItem === null)) continue;

    const settings = parsedItems as ParsedSetting[];
    const compactValueCount = settings.filter(
      (setting) => setting.value.length <= 20,
    ).length;
    if (compactValueCount < Math.max(2, Math.ceil(settings.length * 0.66)))
      continue;

    list.dataset.settingsEnhanced = "true";
    list.classList.add("lab-settings-list");

    for (let i = 0; i < items.length; i++) {
      const item = items[i];
      const setting = settings[i];
      if (!item || !setting) continue;

      item.classList.add("lab-settings-item");
      item.innerHTML =
        `<span class="lab-setting-key">${escapeHtml(setting.key)}</span>` +
        `<span class="lab-setting-value">${escapeHtml(setting.value)}</span>`;
    }
  }
}

function ensureCopyButton(pre: HTMLPreElement, label: string) {
  if (pre.dataset.copyEnhanced === "true") return;

  pre.dataset.copyEnhanced = "true";
  const copyButton = document.createElement("button");
  copyButton.type = "button";
  copyButton.className = "lab-copy-button";
  copyButton.textContent = label;
  copyButton.dataset.defaultLabel = label;
  copyButton.setAttribute("aria-label", "Copy block to clipboard");
  pre.appendChild(copyButton);
}

async function copyTextToClipboard(text: string) {
  if (window.isSecureContext && navigator.clipboard?.writeText) {
    await navigator.clipboard.writeText(text);
    return;
  }

  const activeElement =
    document.activeElement instanceof HTMLElement
      ? document.activeElement
      : null;
  const selection = document.getSelection();
  const previousRanges =
    selection && selection.rangeCount > 0
      ? Array.from({ length: selection.rangeCount }, (_, index) =>
          selection.getRangeAt(index).cloneRange(),
        )
      : [];

  const textarea = document.createElement("textarea");
  textarea.value = text;
  textarea.setAttribute("readonly", "");
  textarea.setAttribute("aria-hidden", "true");
  textarea.style.position = "fixed";
  textarea.style.top = "0";
  textarea.style.left = "-9999px";
  textarea.style.opacity = "0";
  textarea.style.pointerEvents = "none";

  document.body.appendChild(textarea);
  textarea.focus();
  textarea.select();
  textarea.setSelectionRange(0, textarea.value.length);

  try {
    const didCopy = document.execCommand("copy");
    if (!didCopy) {
      throw new Error("Copy command was rejected");
    }
  } finally {
    document.body.removeChild(textarea);
    if (selection) {
      selection.removeAllRanges();
      for (const range of previousRanges) {
        selection.addRange(range);
      }
    }
    activeElement?.focus();
  }
}

export function LabContent({ className, html }: LabContentProps) {
  const containerRef = useRef<HTMLElement>(null);
  const [zoomedImage, setZoomedImage] = useState<ZoomedImageState | null>(null);

  const renderedContent = html
    .split(
      new RegExp(
        `(${escapeRegex(quantizationExplorerToken)}|${escapeRegex(quantizationGridExplorerToken)}|${escapeRegex(objective5ChatToken)}|${escapeRegex(lab3TerminalToken)}|${escapeRegex(lab1ConfidenceToken)}|${escapeRegex(lab1NetronToken)}|${escapeRegex(tokenizerPlaygroundToken)})`,
        "g",
      ),
    )
    .filter(Boolean)
    .map((part, index) => {
      if (part === quantizationExplorerToken) {
        return <QuantizationExplorer key={`quantization-explorer-${index}`} />;
      }

      if (part === quantizationGridExplorerToken) {
        return (
          <QuantizationGridExplorer
            key={`quantization-grid-explorer-${index}`}
          />
        );
      }

      if (part === objective5ChatToken) {
        return <Objective5Chat key={`objective5-chat-${index}`} />;
      }

      if (part === lab3TerminalToken) {
        return <Lab3TerminalFrame key={`lab3-terminal-${index}`} />;
      }

      if (part === lab1ConfidenceToken) {
        return <Lab1ConfidenceChat key={`lab1-confidence-${index}`} />;
      }

      if (part === lab1NetronToken) {
        return <Lab1NetronPanel key={`lab1-netron-${index}`} />;
      }

      if (part === tokenizerPlaygroundToken) {
        return <TokenizerPlaygroundEmbed key={`tokenizer-playground-${index}`} />;
      }

      return (
        <Fragment key={`html-segment-${index}`}>
          <div dangerouslySetInnerHTML={{ __html: part }} />
        </Fragment>
      );
    });

  useEffect(() => {
    const root = containerRef.current;
    if (!root) return;

    const preBlocks = root.querySelectorAll<HTMLPreElement>("pre");
    for (const pre of preBlocks) {
      const code = pre.querySelector<HTMLElement>("code");
      if (!code) continue;

      const blockText = code.textContent ?? "";
      if (looksLikeCliCommand(blockText, code.className)) {
        pre.classList.add("lab-cli-shell");
        ensureCopyButton(pre, "Copy");
        continue;
      }

      if (looksLikePromptTextBlock(blockText, code.className)) {
        pre.classList.add("lab-prompt-card");
        ensureCopyButton(pre, "Copy Text");
      }
    }

    enhanceSettingsLists(root);

    const handleRootClick = (event: Event) => {
      const target = event.target as HTMLElement;
      const button = target.closest<HTMLButtonElement>(
        "button.lab-copy-button",
      );
      if (button) {
        const pre = button.closest("pre");
        const code = pre?.querySelector("code");
        const commandText = code?.textContent?.trimEnd();
        if (!commandText) return;
        const defaultLabel = button.dataset.defaultLabel ?? "Copy";

        void copyTextToClipboard(commandText)
          .then(() => {
            button.textContent = "Copied";
            button.classList.add("is-copied");
            window.setTimeout(() => {
              button.textContent = defaultLabel;
              button.classList.remove("is-copied");
            }, 1200);
          })
          .catch(() => {
            button.textContent = "Failed";
            window.setTimeout(() => {
              button.textContent = defaultLabel;
            }, 1200);
          });
        return;
      }

      const image = target.closest<HTMLImageElement>("img");
      if (!image || !root.contains(image)) return;

      const src = image.getAttribute("src");
      if (!src) return;

      event.preventDefault();
      event.stopPropagation();
      setZoomedImage({
        src,
        alt: image.getAttribute("alt") ?? "",
      });
    };

    root.addEventListener("click", handleRootClick);
    return () => {
      root.removeEventListener("click", handleRootClick);
    };
  }, [html]);

  useEffect(() => {
    if (!zoomedImage) return;

    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";

    const activeElement = document.activeElement;
    const previousFocusedElement =
      activeElement instanceof HTMLElement ? activeElement : null;

    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === "Escape") {
        setZoomedImage(null);
      }
    };

    window.addEventListener("keydown", handleEscape);
    return () => {
      window.removeEventListener("keydown", handleEscape);
      document.body.style.overflow = previousOverflow;
      previousFocusedElement?.focus();
    };
  }, [zoomedImage]);

  return (
    <>
      <article ref={containerRef} className={className}>
        {renderedContent}
      </article>
      {zoomedImage ? (
        <div
          className="lab-image-modal"
          role="presentation"
          onClick={() => setZoomedImage(null)}
        >
          <div
            className="lab-image-modal__surface"
            onClick={(event) => event.stopPropagation()}
          >
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img
              className="lab-image-modal__image"
              src={zoomedImage.src}
              alt={zoomedImage.alt}
            />
          </div>
        </div>
      ) : null}
    </>
  );
}
