import { dedupeResults } from "./dedupe";
import { getSearchConfig } from "./config";
import {
  DEFAULT_SEARCH_SOURCE_MODE,
  modeAllowsBrave,
  modeAllowsCrawler,
  modeAllowsThreads,
  type SearchSourceMode,
} from "./source-mode";
import type { KeywordInput, SearchProvider, SearchResult } from "./types";

export interface OrchestratedSearchResult {
  results: SearchResult[];
  providersUsed: string[];
}

export async function runOrchestratedSearch(
  providers: {
    threads: SearchProvider;
    brave: SearchProvider;
    crawler: SearchProvider;
  },
  keyword: KeywordInput,
  options?: { skipCrawler?: boolean; sourceMode?: SearchSourceMode }
): Promise<OrchestratedSearchResult> {
  const sourceMode = options?.sourceMode ?? DEFAULT_SEARCH_SOURCE_MODE;
  const providersUsed: string[] = [];
  let results: SearchResult[] = [];

  if (modeAllowsThreads(sourceMode) && providers.threads.enabled()) {
    const res = await providers.threads.search({
      keyword: keyword.value,
      limit: keyword.limit,
      source: "threads",
      searchType: "threads_keyword",
      priority: keyword.priority,
    });
    if (res.status === "success" && res.results.length > 0) {
      providersUsed.push("threads");
      results = res.results;
    }
  }

  if (
    results.length === 0 &&
    modeAllowsBrave(sourceMode) &&
    keyword.priority === "high" &&
    providers.brave.enabled()
  ) {
    const res = await providers.brave.search({
      keyword: keyword.value,
      limit: Math.min(keyword.limit, getSearchConfig().brave.resultLimit),
      source: "brave",
      searchType: "web_search",
      priority: keyword.priority,
      patrolMode: true,
      threadsOnly: true,
    });
    if (res.status === "success" && res.results.length > 0) {
      providersUsed.push("brave");
      results = res.results;
    }
  }

  if (
    results.length === 0 &&
    modeAllowsCrawler(sourceMode) &&
    !options?.skipCrawler &&
    providers.crawler.enabled()
  ) {
    const res = await providers.crawler.search({
      keyword: keyword.value,
      limit: keyword.limit,
      source: "crawler",
      searchType: "crawler",
      priority: keyword.priority,
    });
    if (res.status === "success" && res.results.length > 0) {
      providersUsed.push("crawler");
      results = res.results;
    }
  }

  results = dedupeResults(results);
  return { results, providersUsed };
}