import type { OwnPost } from "../domain/types";
import { KEYS } from "../data/mock/keys";
import { readJson, writeJson } from "./storage";

/** 本月成效：距離上次真 API sync 不足此間隔則不重打（5 分鐘） */
export const OWN_POSTS_CURRENT_TTL_MS = 5 * 60 * 1000;

type AccountSyncMeta = {
  /** 上次成功呼叫 sync API 的時間（ms） */
  lastSyncMs: number;
  /** 是否已為「過去月份缺資料」補抓過一次 */
  pastOnceDone: boolean;
};

type MetaStore = Record<string, AccountSyncMeta>;

/** accountId → in-flight sync promise（singleflight） */
const inflight = new Map<string, Promise<OwnPost[]>>();

function loadStore(): MetaStore {
  return readJson(KEYS.ownPostsSyncMeta, {} as MetaStore);
}

function saveStore(store: MetaStore): void {
  writeJson(KEYS.ownPostsSyncMeta, store);
}

export function getOwnPostsSyncMeta(accountId: string): AccountSyncMeta {
  const row = loadStore()[accountId];
  return {
    lastSyncMs: row?.lastSyncMs ?? 0,
    pastOnceDone: Boolean(row?.pastOnceDone),
  };
}

function patchMeta(accountId: string, patch: Partial<AccountSyncMeta>): void {
  const store = loadStore();
  const prev = store[accountId] || { lastSyncMs: 0, pastOnceDone: false };
  store[accountId] = { ...prev, ...patch };
  saveStore(store);
}

export function isCurrentSyncFresh(accountId: string, now = Date.now()): boolean {
  const { lastSyncMs } = getOwnPostsSyncMeta(accountId);
  return lastSyncMs > 0 && now - lastSyncMs < OWN_POSTS_CURRENT_TTL_MS;
}

export function isPastOnceDone(accountId: string): boolean {
  return getOwnPostsSyncMeta(accountId).pastOnceDone;
}

export type OwnPostsSyncReason =
  /** 使用者手動同步：一定打 API */
  | "manual"
  /** 過去月份缺資料：整帳只補抓一次 */
  | "past-once"
  /** 本月定期刷新（5 分鐘） */
  | "current-ttl";

export type OwnPostsSyncResult = {
  posts: OwnPost[];
  /** 是否真的打了 sync API（false = 走 list 或共用 in-flight 已完成後的讀取） */
  fetched: boolean;
  /** 因 TTL／past-once 已完成而跳過 */
  skipped: boolean;
  reason: OwnPostsSyncReason;
};

type Ops = {
  list: (accountId: string) => Promise<OwnPost[]>;
  sync: (accountId: string) => Promise<OwnPost[]>;
};

/**
 * 以 accountId 為 key 的 singleflight sync。
 * - manual：一定呼叫 sync（並發共用同一個 promise）
 * - past-once：若已 pastOnceDone 則只 list
 * - current-ttl：若 5 分鐘內已 sync 則只 list
 */
export async function syncOwnPostsGated(
  accountId: string,
  ops: Ops,
  reason: OwnPostsSyncReason,
): Promise<OwnPostsSyncResult> {
  if (!accountId) {
    return { posts: [], fetched: false, skipped: true, reason };
  }

  const existing = inflight.get(accountId);
  if (existing) {
    const posts = await existing;
    return { posts, fetched: true, skipped: false, reason };
  }

  if (reason === "past-once" && isPastOnceDone(accountId)) {
    const posts = await ops.list(accountId);
    return { posts, fetched: false, skipped: true, reason };
  }

  if (reason === "current-ttl" && isCurrentSyncFresh(accountId)) {
    const posts = await ops.list(accountId);
    return { posts, fetched: false, skipped: true, reason };
  }

  const promise = (async () => {
    try {
      const posts = await ops.sync(accountId);
      const prev = getOwnPostsSyncMeta(accountId);
      patchMeta(accountId, {
        lastSyncMs: Date.now(),
        // 手動或過去月份補抓 → 標記 past-once 完成；TTL 刷新不改旗標
        pastOnceDone:
          prev.pastOnceDone || reason === "past-once" || reason === "manual",
      });
      return posts;
    } finally {
      inflight.delete(accountId);
    }
  })();

  inflight.set(accountId, promise);
  const posts = await promise;
  return { posts, fetched: true, skipped: false, reason };
}

/** 過去月份（不含本月）是否仍全空——用來決定是否觸發 past-once */
export function needsPastMonthBackfill(
  months: Array<{ key: string; posts: number }>,
  currentMonthKey: string,
): boolean {
  return months.some((m) => m.key !== currentMonthKey && m.posts <= 0);
}
