import { keywordSearchViaThreadsApi } from "@/lib/threads-api";
import type { ThreadsApiCredentials } from "@/lib/threads-api/types";
import { cacheGet, cacheSet } from "../cache";
import { getSearchConfig } from "../config";
import { logSearchEvent } from "../logger";
import type { SearchProvider, SearchRequest, SearchResponse, SearchResult } from "../types";

export class ThreadsApiSearchProvider implements SearchProvider {
  constructor(private credentials: ThreadsApiCredentials | null) {}

  name() {
    return "threads" as const;
  }

  enabled(): boolean {
    return getSearchConfig().threads.enabled && !!this.credentials?.accessToken;
  }

  async search(req: SearchRequest): Promise<SearchResponse> {
    if (!this.enabled() || !this.credentials) {
      logSearchEvent({
        kind: "provider",
        provider: "threads",
        status: "unavailable",
        keyword: req.keyword,
      });
      return { provider: "threads", results: [], status: "unavailable" };
    }

    const cfg = getSearchConfig();
    const cacheKey = `search:threads:${req.keyword}:${req.limit}`;
    const cached = cacheGet<SearchResult[]>("threads", cacheKey);
    if (cached) {
      return { provider: "threads", results: cached, status: "success", skipReason: "cache_hit" };
    }

    try {
      const posts = await keywordSearchViaThreadsApi(this.credentials, {
        query: req.keyword,
        limit: req.limit,
        searchType: "RECENT",
      });

      const results: SearchResult[] = posts.map((p) => ({
        title: p.text.slice(0, 120),
        url: p.permalink ?? "",
        snippet: p.text,
        author: p.authorName ?? "",
        publishedAt: p.postedAt,
        source: "threads" as const,
        threadId: p.externalId,
        raw: { likeCount: p.likeCount, replyCount: p.replyCount },
      }));

      cacheSet("threads", cacheKey, results, cfg.threadsCacheTtlMs);

      logSearchEvent({
        kind: "provider",
        provider: "threads",
        status: "success",
        keyword: req.keyword,
        count: results.length,
      });

      return { provider: "threads", results, status: "success" };
    } catch {
      logSearchEvent({
        kind: "provider",
        provider: "threads",
        status: "unavailable",
        keyword: req.keyword,
      });
      return { provider: "threads", results: [], status: "unavailable" };
    }
  }
}