import { cacheGet, cacheSet } from "./cache";
import { getSearchConfig } from "./config";
import { extractThreadId } from "./dedupe";
import { logSearchEvent } from "./logger";
import { canUseDailyQuota, getDailyQuotaUsed, incrementDailyQuota } from "./quota";
import { buildBraveThreadsKeywordQuery } from "./query-builders";
import type { KeywordPriority, SearchResult } from "./types";

export interface BraveExecuteOptions {
  keyword: string;
  limit: number;
  /** 直接指定查詢字串（略過 keyword query builder） */
  query?: string;
  priority?: KeywordPriority;
  /** 巡邏模式：檢查 high priority + 每日額度（預設 true） */
  patrolMode?: boolean;
  /** 僅保留 threads.com 結果（預設 true；fact-check 等可設 false） */
  threadsOnly?: boolean;
}

export interface BraveExecuteResult {
  results: SearchResult[];
  status: "success" | "unavailable" | "skipped";
  skipReason?: string;
  quotaUsed?: number;
  quotaLimit?: number;
  fromCache?: boolean;
}

function mapBraveItems(
  items: Array<{ title?: string; description?: string; url?: string }>,
  limit: number,
  threadsOnly: boolean
): SearchResult[] {
  return items
    .filter((item) => item.url && (!threadsOnly || /threads\.(?:com|net)/i.test(item.url)))
    .slice(0, limit)
    .map((item) => ({
      title: item.title ?? "",
      snippet: item.description ?? "",
      url: item.url ?? "",
      author: "",
      source: "brave" as const,
      threadId: extractThreadId(item.url ?? ""),
    }));
}

export async function executeBraveSearch(opts: BraveExecuteOptions): Promise<BraveExecuteResult> {
  const cfg = getSearchConfig().brave;
  const patrolMode = opts.patrolMode !== false;
  const threadsOnly = opts.threadsOnly !== false;
  const quotaLimit = cfg.dailyLimit;

  if (!cfg.enabled || !cfg.apiKey) {
    return { results: [], status: "unavailable" };
  }

  if (patrolMode && opts.priority && opts.priority !== "high") {
    logSearchEvent({
      kind: "provider",
      provider: "brave",
      status: "skipped",
      keyword: opts.keyword,
      reason: "keyword_priority_not_high",
    });
    return {
      results: [],
      status: "skipped",
      skipReason: "keyword_priority_not_high",
    };
  }

  if (patrolMode && !canUseDailyQuota("brave", quotaLimit)) {
    logSearchEvent({
      kind: "provider",
      provider: "brave",
      status: "skipped",
      keyword: opts.keyword,
      reason: "daily_limit_reached",
      quotaUsed: getDailyQuotaUsed("brave"),
      quotaLimit,
    });
    return {
      results: [],
      status: "skipped",
      skipReason: "daily_limit_reached",
      quotaUsed: getDailyQuotaUsed("brave"),
      quotaLimit,
    };
  }

  const query = opts.query?.trim() || buildBraveThreadsKeywordQuery(opts.keyword);
  const cacheKey = `search:brave:${query}`;
  const cached = cacheGet<SearchResult[]>("brave", cacheKey);
  if (cached) {
    logSearchEvent({
      kind: "provider",
      provider: "brave",
      status: "skipped",
      keyword: opts.keyword,
      reason: "cache_hit",
      count: cached.length,
      quotaUsed: getDailyQuotaUsed("brave"),
      quotaLimit,
    });
    return {
      results: cached.slice(0, opts.limit),
      status: "success",
      skipReason: "cache_hit",
      quotaUsed: getDailyQuotaUsed("brave"),
      quotaLimit,
      fromCache: true,
    };
  }

  try {
    const url = new URL(cfg.baseUrl);
    url.searchParams.set("q", query);
    url.searchParams.set("count", String(Math.min(opts.limit, cfg.resultLimit, 20)));
    url.searchParams.set("country", "tw");
    url.searchParams.set("search_lang", "zh-hant");

    const res = await fetch(url.toString(), {
      headers: {
        Accept: "application/json",
        "X-Subscription-Token": cfg.apiKey,
      },
      signal: AbortSignal.timeout(20_000),
    });

    if (!res.ok) {
      logSearchEvent({
        kind: "provider",
        provider: "brave",
        status: "unavailable",
        keyword: opts.keyword,
      });
      return { results: [], status: "unavailable" };
    }

    const data = (await res.json()) as {
      web?: { results?: Array<{ title?: string; description?: string; url?: string }> };
    };

    const results = mapBraveItems(data.web?.results ?? [], opts.limit, threadsOnly);
    const quotaUsed = patrolMode ? incrementDailyQuota("brave") : getDailyQuotaUsed("brave");
    cacheSet("brave", cacheKey, results, cfg.cacheTtlMs);

    logSearchEvent({
      kind: "provider",
      provider: "brave",
      status: "success",
      keyword: opts.keyword,
      count: results.length,
      quotaUsed,
      quotaLimit,
    });

    return {
      results,
      status: "success",
      quotaUsed,
      quotaLimit,
    };
  } catch {
    logSearchEvent({
      kind: "provider",
      provider: "brave",
      status: "unavailable",
      keyword: opts.keyword,
    });
    return { results: [], status: "unavailable" };
  }
}