import Taro from '@tarojs/taro'
import type { Post } from '@/types/domain'

// Central place that decides *when* a page needs to refetch on `onShow`.
//
// Strategy: pages load once on mount and keep their data. On returning to a page
// we only refetch when (a) a mutation elsewhere explicitly marked the resource
// stale, or (b) the cached data is older than the TTL. This removes the constant
// full reloads (and the blank-list flash) that made navigation feel laggy.

export type ResourceKey = 'feed' | 'myPosts' | 'messages' | 'profile'

const DEFAULT_TTL_MS = 30 * 1000

const lastLoadedAt = new Map<ResourceKey, number>()
const dirty = new Set<ResourceKey>()

/** Record that a resource was just (re)loaded successfully. */
export function markFresh(key: ResourceKey) {
  lastLoadedAt.set(key, Date.now())
  dirty.delete(key)
}

/** Flag resources as needing a refresh next time their page is shown. */
export function markStale(...keys: ResourceKey[]) {
  keys.forEach(key => dirty.add(key))
}

/** Whether a page should refetch on show: dirty, never loaded, or past its TTL. */
export function shouldRefresh(key: ResourceKey, ttlMs: number = DEFAULT_TTL_MS): boolean {
  if (dirty.has(key)) return true
  const at = lastLoadedAt.get(key)
  if (at === undefined) return true
  return Date.now() - at > ttlMs
}

// ---- Cross-page like sync ------------------------------------------------
// Liking a post in one page (e.g. the detail page) should reflect everywhere it
// is shown without a full reload. We broadcast the confirmed like state and let
// each feed-bearing page patch the single affected post in place.

const POST_LIKE_EVENT = 'wq:postLike'
export interface PostLikeChange {
  postId: string
  liked: boolean
  likes: number
}

export function emitPostLike(change: PostLikeChange) {
  Taro.eventCenter.trigger(POST_LIKE_EVENT, change)
}

/** Subscribe to like changes. Returns an unsubscribe function. */
export function onPostLike(handler: (change: PostLikeChange) => void): () => void {
  Taro.eventCenter.on(POST_LIKE_EVENT, handler)
  return () => Taro.eventCenter.off(POST_LIKE_EVENT, handler)
}

// ---- Post hand-off cache --------------------------------------------------
// When opening a post from a list we already hold its full data (including
// resolved image URLs). Stash it so the detail page can paint instantly from the
// same URLs (WeChat image cache hit = no visible reload) while it fetches
// comments / fresh counts in the background.

const POST_CACHE_TTL_MS = 10 * 60 * 1000
const POST_CACHE_MAX = 100

interface CachedPost {
  post: Post
  expiresAt: number
  lastAccess: number
}

const postCache = new Map<string, CachedPost>()

function prunePostCache(now = Date.now()) {
  postCache.forEach((entry, key) => {
    if (entry.expiresAt <= now) postCache.delete(key)
  })

  if (postCache.size <= POST_CACHE_MAX) return

  const overflow = postCache.size - POST_CACHE_MAX
  ;[...postCache.entries()]
    .sort((a, b) => a[1].lastAccess - b[1].lastAccess)
    .slice(0, overflow)
    .forEach(([key]) => postCache.delete(key))
}

export function cachePost(post: Post) {
  if (!post?._id) return
  const now = Date.now()
  postCache.set(post._id, {
    post,
    expiresAt: now + POST_CACHE_TTL_MS,
    lastAccess: now
  })
  prunePostCache(now)
}

export function getCachedPost(postId: string): Post | undefined {
  if (!postId) return undefined
  const entry = postCache.get(postId)
  if (!entry) return undefined

  const now = Date.now()
  if (entry.expiresAt <= now) {
    postCache.delete(postId)
    return undefined
  }

  entry.lastAccess = now
  return entry.post
}
