"use client";

import { useState, useEffect, useCallback, useRef } from "react";
import { ExtractionModal, type ExtractionOutput, type SourceClass } from "./extraction-modal";

type DocumentType = "technical_paper" | "news" | "regulatory" | "documentation" | "blog" | "forum";

interface DocumentContext {
  documentTitle?: string;
  sectionTitle?: string;
  documentType?: DocumentType;
}

interface TextSelectionExtractorProps {
  children: React.ReactNode;
  /** Override document title detection */
  documentTitle?: string;
  /** Override document type detection */
  documentType?: DocumentType;
}

interface SelectionState {
  text: string;
  x: number;
  y: number;
  context: DocumentContext;
}

/**
 * Detect the nearest heading above a DOM node to determine section context
 */
function findNearestHeading(node: Node): string | undefined {
  let current: Node | null = node;

  // Walk up the DOM tree
  while (current) {
    // Check previous siblings for headings
    let sibling = current.previousSibling;
    while (sibling) {
      if (sibling instanceof HTMLElement) {
        // Check if it's a heading
        if (/^H[1-6]$/.test(sibling.tagName)) {
          return sibling.textContent?.trim();
        }
        // Check children for headings (in case heading is nested)
        const heading = sibling.querySelector("h1, h2, h3, h4, h5, h6");
        if (heading) {
          return heading.textContent?.trim();
        }
      }
      sibling = sibling.previousSibling;
    }

    // Move to parent
    current = current.parentNode;
  }

  return undefined;
}

/**
 * Infer document type from page metadata and content
 */
function inferDocumentType(): DocumentType | undefined {
  // Check for common patterns
  const url = window.location.href.toLowerCase();
  const title = document.title.toLowerCase();

  // Technical paper indicators
  if (
    url.includes("arxiv") ||
    url.includes("paper") ||
    title.includes("paper") ||
    document.querySelector('meta[name="citation_title"]')
  ) {
    return "technical_paper";
  }

  // Regulatory indicators
  if (
    url.includes("fda.gov") ||
    url.includes("ema.europa") ||
    url.includes("regulations") ||
    title.includes("regulation")
  ) {
    return "regulatory";
  }

  // Documentation indicators
  if (
    url.includes("/docs/") ||
    url.includes("documentation") ||
    url.includes("readme") ||
    title.includes("documentation")
  ) {
    return "documentation";
  }

  // Blog indicators
  if (
    url.includes("/blog/") ||
    url.includes("medium.com") ||
    url.includes("substack")
  ) {
    return "blog";
  }

  // Forum indicators
  if (
    url.includes("stackoverflow") ||
    url.includes("reddit.com") ||
    url.includes("forum") ||
    url.includes("discuss")
  ) {
    return "forum";
  }

  // News indicators
  if (
    url.includes("news") ||
    document.querySelector('meta[property="og:type"][content="article"]')
  ) {
    return "news";
  }

  return undefined;
}

export function TextSelectionExtractor({
  children,
  documentTitle: propsDocumentTitle,
  documentType: propsDocumentType,
}: TextSelectionExtractorProps) {
  const [selection, setSelection] = useState<SelectionState | null>(null);
  const [isExtracting, setIsExtracting] = useState(false);
  const [extractionResult, setExtractionResult] = useState<ExtractionOutput | null>(null);
  const [extractionError, setExtractionError] = useState<string | null>(null);
  const [sourceClass, setSourceClass] = useState<SourceClass>("Expert");
  const containerRef = useRef<HTMLDivElement>(null);
  const buttonRef = useRef<HTMLButtonElement>(null);

  const handleMouseUp = useCallback(() => {
    // Small delay to let browser finalize selection
    setTimeout(() => {
      const windowSelection = window.getSelection();
      if (!windowSelection || windowSelection.isCollapsed) {
        setSelection(null);
        return;
      }

      const text = windowSelection.toString().trim();
      if (text.length < 20) {
        // Too short to be meaningful
        setSelection(null);
        return;
      }

      // Check if selection is within our container
      const range = windowSelection.getRangeAt(0);
      if (!containerRef.current?.contains(range.commonAncestorContainer)) {
        setSelection(null);
        return;
      }

      // Detect document context
      const context: DocumentContext = {
        documentTitle: propsDocumentTitle || document.title || undefined,
        sectionTitle: findNearestHeading(range.commonAncestorContainer),
        documentType: propsDocumentType || inferDocumentType(),
      };

      // Get position for the floating button
      const rect = range.getBoundingClientRect();
      setSelection({
        text,
        x: rect.left + rect.width / 2,
        y: rect.top - 10, // Above the selection
        context,
      });
    }, 10);
  }, [propsDocumentTitle, propsDocumentType]);

  const handleMouseDown = useCallback((e: MouseEvent) => {
    // Don't clear selection if clicking the extract button
    if (buttonRef.current?.contains(e.target as Node)) {
      return;
    }
    setSelection(null);
  }, []);

  useEffect(() => {
    document.addEventListener("mouseup", handleMouseUp);
    document.addEventListener("mousedown", handleMouseDown);
    return () => {
      document.removeEventListener("mouseup", handleMouseUp);
      document.removeEventListener("mousedown", handleMouseDown);
    };
  }, [handleMouseUp, handleMouseDown]);

  const handleExtract = async () => {
    if (!selection) return;

    setIsExtracting(true);
    setExtractionError(null);

    try {
      const response = await fetch("/api/extract", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          text: selection.text,
          sourceClass,
          context: selection.context,
        }),
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.error || "Extraction failed");
      }

      const result: ExtractionOutput = await response.json();
      setExtractionResult(result);
      setSelection(null);
    } catch (error) {
      setExtractionError(error instanceof Error ? error.message : "Extraction failed");
    } finally {
      setIsExtracting(false);
    }
  };

  const handleCloseModal = () => {
    setExtractionResult(null);
    setExtractionError(null);
  };

  return (
    <div ref={containerRef} className="relative">
      {children}

      {/* Floating Extract Button */}
      {selection && !isExtracting && (
        <div
          className="fixed z-50 flex flex-col items-center gap-2 animate-in fade-in zoom-in duration-150"
          style={{
            left: selection.x,
            top: selection.y,
            transform: "translate(-50%, -100%)",
          }}
        >
          {/* Source class selector */}
          <select
            value={sourceClass}
            onChange={(e) => setSourceClass(e.target.value as SourceClass)}
            className="text-xs bg-card border border-border rounded px-2 py-1 shadow-lg"
            onClick={(e) => e.stopPropagation()}
          >
            <option value="Regulatory">Regulatory (T0)</option>
            <option value="Clinical">Clinical (T1)</option>
            <option value="Observational">Observational (T2)</option>
            <option value="Expert">Expert (T3)</option>
            <option value="Community">Community (T4)</option>
            <option value="Anecdotal">Anecdotal (T5)</option>
          </select>

          <button
            ref={buttonRef}
            onClick={handleExtract}
            className="flex items-center gap-2 px-3 py-2 bg-primary text-primary-foreground rounded-lg shadow-lg hover:bg-primary/90 transition-colors text-sm font-medium"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="16"
              height="16"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth="2"
              strokeLinecap="round"
              strokeLinejoin="round"
            >
              <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
              <polyline points="14,2 14,8 20,8" />
              <line x1="16" y1="13" x2="8" y2="13" />
              <line x1="16" y1="17" x2="8" y2="17" />
              <line x1="10" y1="9" x2="8" y2="9" />
            </svg>
            Extract Claims
          </button>

          {/* Arrow pointing down */}
          <div
            className="w-0 h-0 border-l-[8px] border-l-transparent border-r-[8px] border-r-transparent border-t-[8px] border-t-primary -mt-2"
          />
        </div>
      )}

      {/* Loading indicator */}
      {isExtracting && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
          <div className="bg-card border border-border rounded-lg p-6 shadow-xl flex flex-col items-center gap-4">
            <div className="animate-spin w-8 h-8 border-4 border-primary border-t-transparent rounded-full" />
            <div className="text-sm text-muted-foreground">
              Extracting claims via Claude...
            </div>
            <div className="text-xs text-muted-foreground">
              This may take 10-30 seconds
            </div>
          </div>
        </div>
      )}

      {/* Error toast */}
      {extractionError && (
        <div className="fixed bottom-4 right-4 z-50 bg-destructive text-destructive-foreground px-4 py-3 rounded-lg shadow-lg max-w-md">
          <div className="flex items-start gap-3">
            <span className="text-lg">⚠</span>
            <div>
              <div className="font-medium">Extraction Failed</div>
              <div className="text-sm opacity-90">{extractionError}</div>
            </div>
            <button
              onClick={() => setExtractionError(null)}
              className="ml-auto text-lg hover:opacity-70"
            >
              ×
            </button>
          </div>
        </div>
      )}

      {/* Extraction Results Modal */}
      {extractionResult && (
        <ExtractionModal
          result={extractionResult}
          onClose={handleCloseModal}
          sourceClass={sourceClass}
        />
      )}
    </div>
  );
}
