import { z } from "zod";
import type { ProviderApiKeys } from "./keys";
import { withAgentSystem } from "./agent";
import { generateStructuredObject } from "./generate-structured";
import { getModel } from "./provider";
import type { QualityAssessment, QualityTier, ResearchMap } from "@/lib/types/research";
import { buildTopicAnchorPromptBlock } from "@/lib/topic-anchor";

const filterSchema = z.object({
  items: z.array(
    z.object({
      index: z.number().int().min(0),
      relevanceScore: z.number().min(0).max(100),
      qualityTier: z.enum(["GOOD", "OK", "EXCLUDE"]),
      qualityReason: z.string(),
    })
  ),
});

export interface FilterQualityInput {
  topicLabel: string;
  query: string;
  brief?: string | null;
  researchMap?: ResearchMap | null;
  aiProvider: string;
  aiModel: string;
  apiKeys?: ProviderApiKeys;
  posts: Array<{
    id: string;
    text: string;
    authorName?: string | null;
    searchTag?: string | null;
    likeCount?: number | null;
    replyCount?: number | null;
    replies?: string[] | null;
  }>;
}

function normalizeEngagement(likeCount?: number | null, replyCount?: number | null): number {
  const likes = likeCount ?? 0;
  const replies = replyCount ?? 0;
  const raw = likes * 1.0 + replies * 2.0;
  return Math.min(100, Math.log10(raw + 1) * 25);
}

export function computeCombinedScore(relevanceScore: number, engagementNorm: number): number {
  return relevanceScore * 0.7 + engagementNorm * 0.3;
}

export function computePlacementCombinedScore(
  placementScore: number,
  engagementNorm: number,
  replyCount?: number | null,
  recencyScore?: number | null
): number {
  const replySignal = Math.min(100, (replyCount ?? 0) * 6);
  const recency = recencyScore ?? 35;
  return placementScore * 0.5 + recency * 0.28 + engagementNorm * 0.12 + replySignal * 0.1;
}

export async function filterPostQuality(input: FilterQualityInput): Promise<QualityAssessment[]> {
  if (input.posts.length === 0) return [];

  const model = getModel(input.aiProvider, input.aiModel, input.apiKeys ?? {});

  const similarAccounts = (input.researchMap?.similarAccounts ?? [])
    .slice(0, 8)
    .map((a) => `@${a.username}`)
    .join("、");
  const researchBlock = input.researchMap
    ? `
研究地圖：
- 受眾：${input.researchMap.audienceSummary}
- 目標：${input.researchMap.contentGoal}
- 想了解的問題：${input.researchMap.questions.join("、")}
- 內容支柱：${input.researchMap.pillars.join("、")}
- 排除：${input.researchMap.exclusions.join("、")}
${similarAccounts ? `- 相似帳號（同領域標竿，其貼文通常更值得參考）：${similarAccounts}` : ""}
`
    : "";

  const postsBlock = input.posts
    .map((post, i) => {
      const replyLines = (post.replies ?? []).filter(Boolean).slice(0, 2);
      const replyBlock =
        replyLines.length > 0
          ? `\n熱門留言（觀眾真實反應）：${replyLines.map((r) => `「${r.slice(0, 60)}」`).join(" ")}`
          : "";
      return `[${i}] 標籤：${post.searchTag ?? input.query} | @${post.authorName ?? "匿名"} | ${post.likeCount ?? 0}讚 ${post.replyCount ?? 0}留言
${post.text.slice(0, 280)}${replyBlock}`;
    })
    .join("\n\n");

  const object = await generateStructuredObject({
    model,
    provider: input.aiProvider,
    modelId: input.aiModel,
    schema: filterSchema,
    system: withAgentSystem(`你是 Threads 內容品質審核員。評估每篇貼文是否值得改寫成「新型小語」——觀眾想看的、盡量正確、有故事感的一兩句話。

評分標準：
- relevanceScore 0-100：與主題、受眾需求的相關程度（嚴格扣緊種子關鍵字，略偏題即降分）
- 語錄型、故事感、情緒共鳴、一兩句說中人心 → 提高 relevanceScore
- qualityTier：
  - GOOD：有資訊或故事、結構清楚、值得參考改寫成新型小語
  - OK：角度可參考但內容薄弱、略偏題、或太長不像小語
  - EXCLUDE：業配、偏方、純宣洩無觀點、無關、低質量
- 若有提供「熱門留言」，代表觀眾真實反應：留言越能呼應、討論越熱烈、共鳴越強 → 適度提高 relevanceScore；留言冷淡、跑題或反感 → 降低分數。沒有提供留言時，僅依貼文內容與讚數判斷即可，不要因為缺留言而扣分。
- 帳號只是來源，不是相關性的保證。searchTag 為 @帳號時仍須逐篇審核；個人抒發、生活閒聊、家庭日常、政治或其他主題，即使作者是相似帳號也一律 EXCLUDE。
- 來自 @帳號的貼文，只有內容本身明確命中主題與受眾問題才能給 GOOD/OK；不得因作者是網紅或相似帳號而加分。

請為每篇貼文（用 index 對應）給出評分。qualityReason 用台灣用語繁體中文。`),
    prompt: `主題：${input.topicLabel}
種子關鍵字：${input.query}
${input.brief ? `Brief：${input.brief}` : ""}
${buildTopicAnchorPromptBlock({
  label: input.topicLabel,
  query: input.query,
  brief: input.brief,
  exclusions: input.researchMap?.exclusions,
})}
${researchBlock}

待評估貼文：
${postsBlock}`,
  });

  return object.items
    .filter((item) => item.index >= 0 && item.index < input.posts.length)
    .map((item) => ({
      id: input.posts[item.index].id,
      relevanceScore: item.relevanceScore,
      qualityTier: item.qualityTier as QualityTier,
      qualityReason: item.qualityReason,
    }));
}

export function engagementNormForPost(likeCount?: number | null, replyCount?: number | null): number {
  return normalizeEngagement(likeCount, replyCount);
}
