/**
 * 通用键值状态管理 Store
 *
 * 从 zxFwPricing 拆出，管理 IndexedDB 中的通用键值对状态，
 * 通过快照比对避免不必要的写入。
 */

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useKvStore } from '@/pinia/kv'

const toKey = (keyRaw: string | number) => String(keyRaw || '').trim()
const toKeySnapshot = (value: unknown) => JSON.stringify(value ?? null)
const cloneAny = <T>(value: T): T => {
  if (value == null) return value
  return JSON.parse(JSON.stringify(value)) as T
}

const keyLoadTasks = new Map<string, Promise<unknown>>()

const getKvStoreSafely = () => {
  try {
    return useKvStore()
  } catch {
    return null
  }
}

export const useZxFwPricingKeysStore = defineStore('zxFwPricingKeys', () => {
  /** 通用键值状态 */
  const keyedStates = ref<Record<string, unknown>>({})
  /** 键是否已从 IndexedDB 加载 */
  const keyedLoaded = ref<Record<string, boolean>>({})
  /** 键快照（用于比对是否变更） */
  const keySnapshots = ref<Record<string, string>>({})

  /** 按通用键获取状态 */
  const getKeyState = <T = unknown>(keyRaw: string | number): T | null => {
    const key = toKey(keyRaw)
    if (!key) return null
    if (!Object.prototype.hasOwnProperty.call(keyedStates.value, key)) return null
    return cloneAny(keyedStates.value[key] as T)
  }

  /** 按通用键从缓存或 IndexedDB 加载状态 */
  const loadKeyState = async <T = unknown>(keyRaw: string | number, force = false): Promise<T | null> => {
    const key = toKey(keyRaw)
    if (!key) return null

    const hasState = Object.prototype.hasOwnProperty.call(keyedStates.value, key)
    if (!force && hasState) {
      keyedLoaded.value[key] = true
      if (!keySnapshots.value[key]) {
        keySnapshots.value[key] = toKeySnapshot(keyedStates.value[key])
      }
      return getKeyState<T>(key)
    }

    if (!force && keyLoadTasks.has(key)) return keyLoadTasks.get(key) as Promise<T | null>

    const task = (async () => {
      const kvStore = getKvStoreSafely()
      const raw = kvStore ? await kvStore.getItem<T>(key) : null
      const nextSnapshot = toKeySnapshot(raw)
      const prevSnapshot = keySnapshots.value[key]
      keyedLoaded.value[key] = true
      if (prevSnapshot !== nextSnapshot || !Object.prototype.hasOwnProperty.call(keyedStates.value, key)) {
        keyedStates.value[key] = cloneAny(raw)
        keySnapshots.value[key] = nextSnapshot
      }
      return getKeyState<T>(key)
    })()

    keyLoadTasks.set(key, task)
    try {
      return await task
    } finally {
      keyLoadTasks.delete(key)
    }
  }

  /** 按通用键设置状态并同步版本 */
  const setKeyState = <T = unknown>(
    keyRaw: string | number,
    value: T,
    options?: { force?: boolean }
  ): boolean => {
    const key = toKey(keyRaw)
    if (!key) return false
    const force = options?.force === true
    const nextSnapshot = toKeySnapshot(value)
    const prevSnapshot = keySnapshots.value[key]
    keyedLoaded.value[key] = true
    if (!force && prevSnapshot === nextSnapshot) return false
    keyedStates.value[key] = cloneAny(value)
    keySnapshots.value[key] = nextSnapshot
    return true
  }

  /** 按通用键删除状态 */
  const removeKeyState = (keyRaw: string | number): boolean => {
    const key = toKey(keyRaw)
    if (!key) return false
    const hadValue = Object.prototype.hasOwnProperty.call(keyedStates.value, key)
    delete keyedStates.value[key]
    keyedLoaded.value[key] = true
    keySnapshots.value[key] = toKeySnapshot(null)
    return hadValue
  }

  /** 批量清除指定前缀的键 */
  const removeKeysByPrefix = (prefix: string): boolean => {
    let changed = false
    const allKeys = new Set<string>([
      ...Object.keys(keyedStates.value),
      ...Object.keys(keyedLoaded.value),
      ...Object.keys(keySnapshots.value)
    ])
    for (const key of allKeys) {
      if (!key.startsWith(prefix)) continue
      if (Object.prototype.hasOwnProperty.call(keyedStates.value, key)) {
        delete keyedStates.value[key]
        changed = true
      }
      delete keyedLoaded.value[key]
      delete keySnapshots.value[key]
      keyLoadTasks.delete(key)
    }
    return changed
  }

  /**
   * 直接写入内存状态（不触发版本变更）
   * 供其他 store 在加载时同步数据用
   */
  const setKeyStateSilent = <T = unknown>(key: string, value: T): void => {
    keyedStates.value[key] = cloneAny(value)
    keyedLoaded.value[key] = true
    keySnapshots.value[key] = toKeySnapshot(value)
  }

  return {
    keyedStates,
    keyedLoaded,
    keySnapshots,
    getKeyState,
    loadKeyState,
    setKeyState,
    removeKeyState,
    removeKeysByPrefix,
    setKeyStateSilent
  }
}, {
  persist: true
})
