import type { OwnPost } from "../domain/types";
import { newId } from "./id";
import { translate } from "./i18n/messages";
import { loadUiPrefs } from "./i18n/prefs";
import { readJson, writeJson } from "./storage";
import { nowUnixNano } from "./time";
import { KEYS } from "../data/mock/keys";

function tr(key: string, params?: Record<string, string | number>): string {
  return translate(loadUiPrefs().locale, key, params);
}

function formatCount(n: number): string {
  const locale = loadUiPrefs().locale === "en" ? "en-US" : "zh-TW";
  return n.toLocaleString(locale);
}

export type MonthBucket = {
  /** YYYY-MM */
  key: string;
  /** 顯示：2026/4 */
  label: string;
  posts: number;
  views: number;
  likes: number;
  replies: number;
  reposts: number;
  quotes: number;
  shares: number;
  /** 0–1 */
  engagementRate: number;
  /** 真實貼文聚合 or 補齊 mock 歷史 */
  source: "posts" | "estimate";
};

export type AccountInsightsReport = {
  accountId: string;
  months: MonthBucket[];
  current: MonthBucket;
  previous: MonthBucket | null;
  /** 相對上月變化 %（null = 無法比） */
  delta: {
    views: number | null;
    likes: number | null;
    replies: number | null;
    posts: number | null;
    engagementRate: number | null;
  };
  topPosts: OwnPost[];
  /** 分析結論 */
  analysis: string[];
  /** 可執行建議 */
  recommendations: string[];
  totalPosts: number;
  /** 互動率平均（有 views 的貼） */
  avgEngagementRate: number;
};

/** 單月分析封存：可回看每個月的結論與建議 */
export type AccountInsightsSnapshot = {
  id: string;
  account_id: string;
  /** YYYY-MM */
  month_key: string;
  month_label: string;
  /** 產生／覆寫分析的時間 unix ns */
  analyzed_at: number;
  metrics: {
    posts: number;
    views: number;
    likes: number;
    replies: number;
    engagementRate: number;
    source: MonthBucket["source"];
  };
  delta: {
    views: number | null;
    likes: number | null;
    replies: number | null;
    posts: number | null;
    engagementRate: number | null;
  };
  analysis: string[];
  recommendations: string[];
  /** 當月 Top 貼摘要（封存文字，不依貼文刪除而消失） */
  top_highlights: string[];
};

export function monthKeyFromDate(d: Date = new Date()): string {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`;
}

export function monthLabel(key: string): string {
  const [y, m] = key.split("-");
  return `${y}/${Number(m)}`;
}

function loadAllSnapshots(): AccountInsightsSnapshot[] {
  return readJson(KEYS.accountInsightHistory, [] as AccountInsightsSnapshot[]);
}

function saveAllSnapshots(list: AccountInsightsSnapshot[]): void {
  writeJson(KEYS.accountInsightHistory, list.slice(0, 240));
}

export function listInsightSnapshots(accountId: string): AccountInsightsSnapshot[] {
  return loadAllSnapshots()
    .filter((s) => s.account_id === accountId)
    .slice()
    .sort((a, b) => (a.month_key < b.month_key ? 1 : a.month_key > b.month_key ? -1 : 0));
}

export function getInsightSnapshot(
  accountId: string,
  monthKey: string,
): AccountInsightsSnapshot | null {
  return (
    loadAllSnapshots().find((s) => s.account_id === accountId && s.month_key === monthKey) || null
  );
}

/** 寫入／覆寫某帳某月分析 */
export function saveInsightSnapshot(snap: AccountInsightsSnapshot): AccountInsightsSnapshot {
  const list = loadAllSnapshots().filter(
    (s) => !(s.account_id === snap.account_id && s.month_key === snap.month_key),
  );
  list.unshift(snap);
  saveAllSnapshots(list);
  return snap;
}

/** 刪除某帳某月分析（空月不該留假結論） */
export function removeInsightSnapshot(accountId: string, monthKey: string): void {
  const list = loadAllSnapshots().filter(
    (s) => !(s.account_id === accountId && s.month_key === monthKey),
  );
  saveAllSnapshots(list);
}

/** 該月是否有足夠真實數據可寫結論（至少 1 則貼文） */
export function monthHasRealData(month: Pick<MonthBucket, "posts">): boolean {
  return (month.posts || 0) > 0;
}

function snapshotFromParts(opts: {
  accountId: string;
  month: MonthBucket;
  previous: MonthBucket | null;
  analysis: string[];
  recommendations: string[];
  topHighlights: string[];
  forceNewId?: boolean;
  existingId?: string;
}): AccountInsightsSnapshot {
  const delta = {
    views: opts.previous ? pctChange(opts.month.views, opts.previous.views) : null,
    likes: opts.previous ? pctChange(opts.month.likes, opts.previous.likes) : null,
    replies: opts.previous ? pctChange(opts.month.replies, opts.previous.replies) : null,
    posts: opts.previous ? pctChange(opts.month.posts, opts.previous.posts) : null,
    engagementRate: opts.previous
      ? pctChange(opts.month.engagementRate * 100, opts.previous.engagementRate * 100)
      : null,
  };
  return {
    id: opts.existingId || newId("ain"),
    account_id: opts.accountId,
    month_key: opts.month.key,
    month_label: opts.month.label,
    analyzed_at: nowUnixNano(),
    metrics: {
      posts: opts.month.posts,
      views: opts.month.views,
      likes: opts.month.likes,
      replies: opts.month.replies,
      engagementRate: opts.month.engagementRate,
      source: opts.month.source,
    },
    delta,
    analysis: opts.analysis,
    recommendations: opts.recommendations,
    top_highlights: opts.topHighlights,
  };
}

/**
 * 依目前 report 維護分析歷史。
 * - 該月 posts=0：不寫結論，並清掉舊的假 snapshot
 * - 有貼文才建／更新分析（本月可 force 重算）
 */
export function ensureInsightHistory(
  report: AccountInsightsReport,
  opts?: { forceCurrent?: boolean },
): AccountInsightsSnapshot[] {
  const months = report.months;
  const monthKeys = new Set(months.map((m) => m.key));

  // 清掉已不在視窗外、或空月卻殘留假結論的紀錄
  for (const snap of listInsightSnapshots(report.accountId)) {
    const bucket = months.find((m) => m.key === snap.month_key);
    if (!monthKeys.has(snap.month_key)) continue;
    if (bucket && !monthHasRealData(bucket)) {
      removeInsightSnapshot(report.accountId, snap.month_key);
    }
    // 舊假資料：metrics.posts=0 卻還有分析句
    if ((snap.metrics?.posts || 0) <= 0 && (snap.analysis?.length || 0) > 0) {
      removeInsightSnapshot(report.accountId, snap.month_key);
    }
  }

  for (let i = 0; i < months.length; i++) {
    const month = months[i]!;
    // 沒有真實貼文 → 不亂下結論
    if (!monthHasRealData(month)) {
      removeInsightSnapshot(report.accountId, month.key);
      continue;
    }

    // 月比只在「前月也有真實貼文」時才有意義
    const rawPrev = i > 0 ? months[i - 1]! : null;
    const previous = rawPrev && monthHasRealData(rawPrev) ? rawPrev : null;
    const existing = getInsightSnapshot(report.accountId, month.key);
    const isCurrent = i === months.length - 1;
    if (existing && !(isCurrent && opts?.forceCurrent)) continue;

    const monthTop = topPostsForMonth(
      // report.topPosts 是全帳本月 top；歷史月用 metrics 敘事 + 空 highlights 即可
      isCurrent ? report.topPosts : [],
      month.key,
      3,
    );
    // 若是本月，topPosts 已是本月；仍再 filter 保險
    const highlights = (isCurrent ? report.topPosts : monthTop).slice(0, 3).map((p) => {
      const head = (p.insight || p.formula_summary || p.text).slice(0, 80);
      return `${p.topic_tag ? `【${p.topic_tag}】` : ""}${head}${head.length >= 80 ? "…" : ""}`;
    });

    const narrative = buildNarrative({
      current: month,
      previous,
      delta: {
        views: previous ? pctChange(month.views, previous.views) : null,
        likes: previous ? pctChange(month.likes, previous.likes) : null,
        replies: previous ? pctChange(month.replies, previous.replies) : null,
        posts: previous ? pctChange(month.posts, previous.posts) : null,
        engagementRate: previous
          ? pctChange(month.engagementRate * 100, previous.engagementRate * 100)
          : null,
      },
      topPosts: isCurrent ? report.topPosts : [],
      avgEngagementRate: isCurrent ? report.avgEngagementRate : month.engagementRate,
      totalPosts: month.posts,
      monthLabel: month.label,
    });

    // 仍無任何可說的結論 → 不存 snapshot
    if (narrative.analysis.length === 0 && narrative.recommendations.length === 0) {
      removeInsightSnapshot(report.accountId, month.key);
      continue;
    }

    saveInsightSnapshot(
      snapshotFromParts({
        accountId: report.accountId,
        month,
        previous,
        analysis: narrative.analysis,
        recommendations: narrative.recommendations,
        topHighlights: highlights,
        existingId: existing?.id,
      }),
    );
  }

  return listInsightSnapshots(report.accountId);
}

function engagementOf(p: OwnPost): number {
  const views = p.view_count || 0;
  if (views <= 0) return 0;
  const eng =
    (p.like_count || 0) +
    (p.reply_count || 0) +
    (p.repost_count || 0) +
    (p.quote_count || 0) +
    (p.share_count || 0);
  return eng / views;
}

/** published_at unix ns → YYYY-MM */
export function monthKeyOfPost(p: OwnPost): string {
  const ms = p.published_at > 0 ? Math.floor(p.published_at / 1_000_000) : Date.now();
  return monthKeyFromDate(new Date(ms));
}

export function filterPostsByMonth(posts: OwnPost[], monthKey: string): OwnPost[] {
  return posts.filter((p) => monthKeyOfPost(p) === monthKey);
}

export function scoreOwnPost(p: OwnPost): number {
  return (
    (p.view_count || 0) +
    (p.like_count || 0) * 8 +
    (p.reply_count || 0) * 20 +
    (p.repost_count || 0) * 15 +
    (p.quote_count || 0) * 12
  );
}

/** 指定月份表現較佳貼文 */
export function topPostsForMonth(posts: OwnPost[], monthKey: string, limit = 5): OwnPost[] {
  return filterPostsByMonth(posts, monthKey)
    .slice()
    .sort((a, b) => scoreOwnPost(b) - scoreOwnPost(a))
    .slice(0, limit);
}

function emptyBucket(key: string, source: MonthBucket["source"] = "estimate"): MonthBucket {
  return {
    key,
    label: monthLabel(key),
    posts: 0,
    views: 0,
    likes: 0,
    replies: 0,
    reposts: 0,
    quotes: 0,
    shares: 0,
    engagementRate: 0,
    source,
  };
}

function finalizeBucket(b: MonthBucket): MonthBucket {
  const eng =
    b.likes + b.replies + b.reposts + b.quotes + b.shares;
  return {
    ...b,
    engagementRate: b.views > 0 ? eng / b.views : 0,
  };
}

function lastNMonthKeys(n: number, from = new Date()): string[] {
  const keys: string[] = [];
  const d = new Date(from.getFullYear(), from.getMonth(), 1);
  for (let i = n - 1; i >= 0; i--) {
    const x = new Date(d.getFullYear(), d.getMonth() - i, 1);
    keys.push(monthKeyFromDate(x));
  }
  return keys;
}

function pctChange(curr: number, prev: number): number | null {
  if (prev <= 0 && curr <= 0) return 0;
  if (prev <= 0) return curr > 0 ? 100 : null;
  return Math.round(((curr - prev) / prev) * 1000) / 10;
}

/**
 * 由已同步貼文聚合近 N 月成效（只算真實數據；無貼文的月份為 0，不造假估測）。
 */
export function buildAccountInsights(
  accountId: string,
  posts: OwnPost[],
  monthCount = 6,
): AccountInsightsReport {
  const mine = posts.filter((p) => p.account_id === accountId);
  const keys = lastNMonthKeys(monthCount);
  const byMonth = new Map<string, MonthBucket>();

  for (const k of keys) byMonth.set(k, emptyBucket(k, "posts"));

  for (const p of mine) {
    // published_at = unix ns；異常 0 則歸入本月，避免整批落在窗外
    const ms =
      p.published_at > 0 ? Math.floor(p.published_at / 1_000_000) : Date.now();
    const key = monthKeyFromDate(new Date(ms));
    if (!byMonth.has(key)) continue;
    const b = byMonth.get(key)!;
    b.posts += 1;
    b.views += p.view_count || 0;
    b.likes += p.like_count || 0;
    b.replies += p.reply_count || 0;
    b.reposts += p.repost_count || 0;
    b.quotes += p.quote_count || 0;
    b.shares += p.share_count || 0;
    b.source = "posts";
  }

  for (const k of keys) {
    byMonth.set(k, finalizeBucket(byMonth.get(k)!));
  }

  const months = keys.map((k) => byMonth.get(k)!);
  const current = months[months.length - 1]!;
  // 前月沒貼文就不做月比（避免 0→有數 顯示 +100% 假結論）
  const rawPrev = months.length >= 2 ? months[months.length - 2]! : null;
  const previous = rawPrev && monthHasRealData(rawPrev) ? rawPrev : null;

  const delta = {
    views: previous && monthHasRealData(current) ? pctChange(current.views, previous.views) : null,
    likes: previous && monthHasRealData(current) ? pctChange(current.likes, previous.likes) : null,
    replies:
      previous && monthHasRealData(current) ? pctChange(current.replies, previous.replies) : null,
    posts: previous && monthHasRealData(current) ? pctChange(current.posts, previous.posts) : null,
    engagementRate:
      previous && monthHasRealData(current)
        ? pctChange(current.engagementRate * 100, previous.engagementRate * 100)
        : null,
  };

  const topPosts = topPostsForMonth(mine, current.key, 5);

  const withViews = mine.filter((p) => (p.view_count || 0) > 0);
  const avgEngagementRate = withViews.length
    ? withViews.reduce((s, p) => s + engagementOf(p), 0) / withViews.length
    : current.engagementRate;

  const { analysis, recommendations } = buildNarrative({
    current,
    previous,
    delta,
    topPosts,
    avgEngagementRate,
    totalPosts: mine.length,
    monthLabel: current.label,
  });

  return {
    accountId,
    months,
    current,
    previous,
    delta,
    topPosts,
    analysis,
    recommendations,
    totalPosts: mine.length,
    avgEngagementRate,
  };
}

/**
 * 只根據該月真實指標寫結論；沒貼文／沒可比數字就不硬寫。
 */
function buildNarrative(opts: {
  current: MonthBucket;
  previous: MonthBucket | null;
  delta: AccountInsightsReport["delta"];
  topPosts: OwnPost[];
  avgEngagementRate: number;
  totalPosts: number;
  monthLabel?: string;
}): { analysis: string[]; recommendations: string[] } {
  const { current, previous, delta, topPosts, avgEngagementRate } = opts;
  const when = opts.monthLabel || current.label || tr("insights.thisMonth");
  const analysis: string[] = [];
  const recommendations: string[] = [];

  // 空月：完全不說話
  if (!monthHasRealData(current)) {
    return { analysis: [], recommendations: [] };
  }

  analysis.push(
    tr("insights.narrative.summary", {
      when,
      posts: current.posts,
      views: formatCount(current.views),
      likes: current.likes,
      replies: current.replies,
    }),
  );

  // 僅在前月也有貼文時才比
  if (previous && monthHasRealData(previous) && delta.views != null) {
    if (delta.views > 8 || delta.views < -8) {
      analysis.push(
        tr("insights.narrative.viewsDelta", {
          delta: fmtDelta(delta.views),
          prev: formatCount(previous.views),
          curr: formatCount(current.views),
        }),
      );
    } else {
      analysis.push(tr("insights.narrative.viewsFlat", { delta: fmtDelta(delta.views) }));
    }
  }

  if (previous && monthHasRealData(previous) && delta.replies != null) {
    if (delta.replies > 10) {
      analysis.push(tr("insights.narrative.repliesUp", { delta: fmtDelta(delta.replies) }));
    } else if (delta.replies < -10) {
      analysis.push(tr("insights.narrative.repliesDelta", { delta: fmtDelta(delta.replies) }));
    }
  }

  // 有瀏覽才談互動率，避免 0 瀏覽硬算 0% 再亂評
  if (current.views > 0) {
    const engPct = Math.round(avgEngagementRate * 1000) / 10;
    analysis.push(tr("insights.narrative.engRate", { pct: engPct }));
    if (engPct < 2) {
      recommendations.push(tr("insights.narrative.engLow"));
    } else if (engPct >= 4) {
      recommendations.push(tr("insights.narrative.engGood"));
    }
  } else if (current.likes + current.replies > 0) {
    analysis.push(tr("insights.narrative.zeroViews"));
  }

  const top = topPosts[0];
  if (top) {
    const snippet = (top.insight || top.formula_summary || top.text).slice(0, 72);
    analysis.push(
      tr("insights.narrative.highlight", { snippet: `${snippet}${snippet.length >= 72 ? "…" : ""}` }),
    );
  }

  if (current.posts < 3) {
    recommendations.push(tr("insights.narrative.smallSample"));
  }

  return {
    analysis: analysis.slice(0, 5),
    recommendations: recommendations.slice(0, 3),
  };
}

export function fmtDelta(n: number | null | undefined): string {
  if (n == null || Number.isNaN(n)) return "—";
  if (n > 0) return `+${n}%`;
  if (n < 0) return `${n}%`;
  return "0%";
}

export function fmtEngRate(rate: number): string {
  return `${Math.round(rate * 1000) / 10}%`;
}
