// 业务时钟缓存
//
// sandbox 模式下，小程序的 performance / task-list / customer-records 等页面
// 需要按"业务日"而不是"真实今天"构造请求参数。
//
// 用法：
//   import { getBusinessClock, getBusinessYearMonth } from '../../utils/runtime-clock'
//   const clock = await getBusinessClock()
//   wx.request({ url: ..., data: { year: clock.business_year, month: clock.business_month } })
//
// 缓存策略：
// - 单例 in-memory cache，最多 60 秒；过期后自动重新拉取。
// - 切换沙箱后，建议页面调用 `clearBusinessClockCache()` 主动失效。

import { fetchRuntimeClock, type RuntimeClock } from '../services/api'

const TTL_MS = 60_000 // 60 秒缓存，足以覆盖一次页面进入

let cached: { value: RuntimeClock; ts: number } | null = null
let inflight: Promise<RuntimeClock> | null = null

/** 主动清空业务时钟缓存（沙箱切换、登出后调用）。 */
export function clearBusinessClockCache(): void {
  cached = null
  inflight = null
}

/** 拉取业务时钟（可能命中缓存）。失败时降级为本地"今天"。 */
export async function getBusinessClock(force = false): Promise<RuntimeClock> {
  const now = Date.now()
  if (!force && cached && now - cached.ts < TTL_MS) {
    return cached.value
  }
  if (inflight) {
    return inflight
  }
  inflight = (async () => {
    try {
      const clock = await fetchRuntimeClock()
      cached = { value: clock, ts: Date.now() }
      return clock
    } catch (err) {
      console.warn('[runtime-clock] 拉取业务时钟失败，降级为本地时间', err)
      return localFallback()
    } finally {
      inflight = null
    }
  })()
  return inflight
}

/** 便捷方法：返回业务年月 (YYYY-MM)。 */
export async function getBusinessYearMonth(): Promise<{ year: number; month: number; label: string }> {
  const clock = await getBusinessClock()
  return {
    year: clock.business_year,
    month: clock.business_month,
    label: `${clock.business_year}年${clock.business_month}月`,
  }
}

/** 便捷方法：返回业务日 (YYYY-MM-DD)。 */
export async function getBusinessDate(): Promise<string> {
  return (await getBusinessClock()).business_date
}

function localFallback(): RuntimeClock {
  const d = new Date()
  const year = d.getFullYear()
  const month = d.getMonth() + 1
  const ymd = `${year}-${String(month).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
  return {
    mode: 'live',
    business_date: ymd,
    business_year: year,
    business_month: month,
    business_year_month: `${year}-${String(month).padStart(2, '0')}`,
    business_now: d.toISOString(),
    is_sandbox: false,
    sandbox_date: null,
    sandbox_instance_id: null,
  }
}
