// Full-text search within PDF documents

import { PDFDocumentProxy } from "pdfjs-dist";

interface SearchResult {
  pageNumber: number;
  text: string;
  index: number;
  context: string;
}

// Full-text search within PDF documents
// Procedural implementation (no OOP)

interface SearchResult {
  pageNumber: number;
  text: string;
  index: number;
  context: string;
}

interface PDFSearchState {
  doc: PDFDocumentProxy | null;
  searchResults: SearchResult[];
  currentResultIndex: number;
}

async function initializePDFSearch(
  doc: PDFDocumentProxy,
): Promise<PDFSearchState> {
  return {
    doc,
    searchResults: [],
    currentResultIndex: 0,
  };
}

async function searchPDF(
  state: PDFSearchState,
  query: string,
): Promise<PDFSearchState> {
  if (!state.doc) return state;

  const searchResults: SearchResult[] = [];
  const lowerQuery = query.toLowerCase();

  for (let pageNum = 1; pageNum <= state.doc.numPages; pageNum++) {
    const page = await state.doc.getPage(pageNum);
    const textContent = await page.getTextContent();

    let fullText = "";
    const textItems = textContent.items.map((item) => {
      if (typeof item === "string") return "";
      fullText += item.str;
      return item.str;
    });

    const pageText = textItems.join(" ");
    const matches = findSearchMatches(pageText, lowerQuery, pageNum);

    searchResults.push(...matches);
  }

  return { ...state, searchResults };
}

function findSearchMatches(
  text: string,
  query: string,
  pageNumber: number,
): SearchResult[] {
  const matches: SearchResult[] = [];
  const lowerText = text.toLowerCase();
  let index = 0;

  while ((index = lowerText.indexOf(query, index)) !== -1) {
    const start = Math.max(0, index - 50);
    const end = Math.min(text.length, index + query.length + 50);
    const context = text.slice(start, end);

    matches.push({
      pageNumber,
      text: text.slice(index, index + query.length),
      index,
      context,
    });

    index += query.length;
  }

  return matches;
}

function goToNextSearchResult(
  state: PDFSearchState,
): PDFSearchState & { result: SearchResult | null } {
  if (state.searchResults.length === 0) {
    return { ...state, result: null };
  }

  const newIndex = (state.currentResultIndex + 1) % state.searchResults.length;
  return {
    ...state,
    currentResultIndex: newIndex,
    result: state.searchResults[newIndex],
  };
}

function goToPreviousSearchResult(
  state: PDFSearchState,
): PDFSearchState & { result: SearchResult | null } {
  if (state.searchResults.length === 0) {
    return { ...state, result: null };
  }

  const newIndex =
    (state.currentResultIndex - 1 + state.searchResults.length) %
    state.searchResults.length;
  return {
    ...state,
    currentResultIndex: newIndex,
    result: state.searchResults[newIndex],
  };
}

function getSearchResultCount(state: PDFSearchState): number {
  return state.searchResults.length;
}

function clearSearchResults(state: PDFSearchState): PDFSearchState {
  return {
    ...state,
    searchResults: [],
    currentResultIndex: 0,
  };
}
