/**
 * 合同附加费用状态管理 Store
 *
 * 从 zxFwPricing 拆出，管理合同附加费用的主表和子方法状态。
 * 包括 additional-work（附加工作）和 reserve（预留金）两种费用类型。
 */

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { useZxFwPricingKeysStore } from '@/pinia/zxFwPricingKeys'
import type { HtFeeMainState, HtFeeMethodType, HtFeeMethodPayload } from '@/types/pricing'

const HT_FEE_MAIN_KEY_PATTERN = /^htExtraFee-(.+)-(additional-work|reserve)$/
const HT_FEE_METHOD_TYPES: HtFeeMethodType[] = ['rate-fee', 'hourly-fee', 'quantity-unit-price-fee']

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 normalizeHtFeeMainState = (
  payload: Partial<HtFeeMainState> | null | undefined
): HtFeeMainState => ({
  detailRows: Array.isArray(payload?.detailRows) ? cloneAny(payload.detailRows) : []
})

/** 解析附加费用主表存储键 */
export const parseHtFeeMainStorageKey = (keyRaw: string | number) => {
  const key = toKey(keyRaw)
  if (!key) return null
  const match = HT_FEE_MAIN_KEY_PATTERN.exec(key)
  if (!match) return null
  const contractId = String(match[1] || '').trim()
  const feeType = String(match[2] || '').trim()
  if (!contractId || !feeType) return null
  return { key, contractId, feeType, mainStorageKey: key }
}

/** 解析附加费用子方法存储键 */
export const parseHtFeeMethodStorageKey = (keyRaw: string | number) => {
  const key = toKey(keyRaw)
  if (!key) return null
  for (const method of HT_FEE_METHOD_TYPES) {
    const suffix = `-${method}`
    if (!key.endsWith(suffix)) continue
    const withoutMethod = key.slice(0, key.length - suffix.length)
    const mainMatch = /^(htExtraFee-.+-(?:additional-work|reserve))-(.+)$/.exec(withoutMethod)
    if (!mainMatch) continue
    const mainStorageKey = String(mainMatch[1] || '').trim()
    const rowId = String(mainMatch[2] || '').trim()
    if (!mainStorageKey || !rowId) continue
    return { key, mainStorageKey, rowId, method }
  }
  return null
}

export const useZxFwPricingHtFeeStore = defineStore('zxFwPricingHtFee', () => {
  /** 附加费用主表状态 */
  const htFeeMainStates = ref<Record<string, HtFeeMainState>>({})
  /** 附加费用子方法状态 */
  const htFeeMethodStates = ref<
    Record<string, Record<string, Partial<Record<HtFeeMethodType, HtFeeMethodPayload>>>>
  >({})

  /* ----------------------------------------------------------------
   * 主表操作
   * ---------------------------------------------------------------- */

  /** 获取附加费用主表状态 */
  const getHtFeeMainState = <TRow = unknown>(
    mainStorageKeyRaw: string | number
  ): HtFeeMainState<TRow> | null => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    if (!mainStorageKey) return null
    return (htFeeMainStates.value[mainStorageKey] as HtFeeMainState<TRow> | undefined) || null
  }

  /** 设置附加费用主表状态并同步版本 */
  const setHtFeeMainState = <TRow = unknown>(
    mainStorageKeyRaw: string | number,
    payload: Partial<HtFeeMainState<TRow>> | null | undefined,
    options?: { force?: boolean; syncKeyState?: boolean }
  ): boolean => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    if (!mainStorageKey) return false
    const force = options?.force === true
    const syncKeyState = options?.syncKeyState !== false
    const normalized = payload == null ? null : normalizeHtFeeMainState(payload)
    const prevSnapshot = toKeySnapshot(getHtFeeMainState(mainStorageKey))
    const nextSnapshot = toKeySnapshot(normalized)
    if (!force && prevSnapshot === nextSnapshot) return false

    if (normalized == null) {
      delete htFeeMainStates.value[mainStorageKey]
    } else {
      htFeeMainStates.value[mainStorageKey] = normalized
    }

    if (syncKeyState) {
      const keysStore = useZxFwPricingKeysStore()
      if (normalized == null) {
        keysStore.removeKeyState(mainStorageKey)
      } else {
        keysStore.setKeyState(mainStorageKey, cloneAny(normalized), { force: true })
      }
    }
    return true
  }

  /** 从缓存或 IndexedDB 加载附加费用主表状态 */
  const loadHtFeeMainState = async <TRow = unknown>(
    mainStorageKeyRaw: string | number,
    force = false
  ): Promise<HtFeeMainState<TRow> | null> => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    if (!mainStorageKey) return null
    if (!force) {
      const existing = getHtFeeMainState<TRow>(mainStorageKey)
      if (existing) return existing
    }
    const keysStore = useZxFwPricingKeysStore()
    const payload = await keysStore.loadKeyState<HtFeeMainState<TRow>>(mainStorageKey, force)
    if (!payload) {
      setHtFeeMainState(mainStorageKey, null, { force: true, syncKeyState: false })
      return null
    }
    setHtFeeMainState(mainStorageKey, payload, { force: true, syncKeyState: false })
    return getHtFeeMainState<TRow>(mainStorageKey)
  }

  /** 删除附加费用主表状态 */
  const removeHtFeeMainState = (mainStorageKeyRaw: string | number) =>
    setHtFeeMainState(mainStorageKeyRaw, null)

  /* ----------------------------------------------------------------
   * 子方法操作
   * ---------------------------------------------------------------- */

  const ensureMethodContainer = (mainStorageKey: string, rowId: string) => {
    if (!htFeeMethodStates.value[mainStorageKey]) {
      htFeeMethodStates.value[mainStorageKey] = {}
    }
    if (!htFeeMethodStates.value[mainStorageKey][rowId]) {
      htFeeMethodStates.value[mainStorageKey][rowId] = {}
    }
    return htFeeMethodStates.value[mainStorageKey][rowId]
  }

  /** 获取附加费用子方法存储键 */
  const getHtFeeMethodStorageKey = (
    mainStorageKeyRaw: string | number,
    rowIdRaw: string | number,
    method: HtFeeMethodType
  ): string => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    const rowId = toKey(rowIdRaw)
    if (!mainStorageKey || !rowId) return ''
    return `${mainStorageKey}-${rowId}-${method}`
  }

  /** 获取附加费用子方法状态 */
  const getHtFeeMethodState = <TPayload = HtFeeMethodPayload>(
    mainStorageKeyRaw: string | number,
    rowIdRaw: string | number,
    method: HtFeeMethodType
  ): TPayload | null => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    const rowId = toKey(rowIdRaw)
    if (!mainStorageKey || !rowId) return null
    const value = htFeeMethodStates.value[mainStorageKey]?.[rowId]?.[method]
    return value == null ? null : (cloneAny(value) as TPayload)
  }

  /** 设置附加费用子方法状态并同步版本 */
  const setHtFeeMethodState = <TPayload = HtFeeMethodPayload>(
    mainStorageKeyRaw: string | number,
    rowIdRaw: string | number,
    method: HtFeeMethodType,
    payload: TPayload | null | undefined,
    options?: { force?: boolean; syncKeyState?: boolean }
  ): boolean => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    const rowId = toKey(rowIdRaw)
    if (!mainStorageKey || !rowId) return false
    const storageKey = getHtFeeMethodStorageKey(mainStorageKey, rowId, method)
    if (!storageKey) return false
    const force = options?.force === true
    const syncKeyState = options?.syncKeyState !== false
    const prevSnapshot = toKeySnapshot(getHtFeeMethodState(mainStorageKey, rowId, method))
    const nextSnapshot = toKeySnapshot(payload ?? null)
    if (!force && prevSnapshot === nextSnapshot) return false

    if (payload == null) {
      const byRow = htFeeMethodStates.value[mainStorageKey]?.[rowId]
      if (byRow) {
        delete byRow[method]
        if (Object.keys(byRow).length === 0) {
          delete htFeeMethodStates.value[mainStorageKey][rowId]
          if (Object.keys(htFeeMethodStates.value[mainStorageKey]).length === 0) {
            delete htFeeMethodStates.value[mainStorageKey]
          }
        }
      }
    } else {
      const container = ensureMethodContainer(mainStorageKey, rowId)
      container[method] = cloneAny(payload)
    }

    if (syncKeyState) {
      const keysStore = useZxFwPricingKeysStore()
      if (payload == null) {
        keysStore.removeKeyState(storageKey)
      } else {
        keysStore.setKeyState(storageKey, cloneAny(payload), { force: true })
      }
    }
    return true
  }

  /** 从缓存或 IndexedDB 加载附加费用子方法状态 */
  const loadHtFeeMethodState = async <TPayload = HtFeeMethodPayload>(
    mainStorageKeyRaw: string | number,
    rowIdRaw: string | number,
    method: HtFeeMethodType,
    force = false
  ): Promise<TPayload | null> => {
    const mainStorageKey = toKey(mainStorageKeyRaw)
    const rowId = toKey(rowIdRaw)
    if (!mainStorageKey || !rowId) return null
    if (!force) {
      const existing = getHtFeeMethodState<TPayload>(mainStorageKey, rowId, method)
      if (existing != null) return existing
    }
    const storageKey = getHtFeeMethodStorageKey(mainStorageKey, rowId, method)
    const keysStore = useZxFwPricingKeysStore()
    const payload = await keysStore.loadKeyState<TPayload>(storageKey, force)
    if (payload == null) {
      setHtFeeMethodState(mainStorageKey, rowId, method, null, { force: true, syncKeyState: false })
      return null
    }
    setHtFeeMethodState(mainStorageKey, rowId, method, payload, { force: true, syncKeyState: false })
    return getHtFeeMethodState<TPayload>(mainStorageKey, rowId, method)
  }

  /** 删除附加费用子方法状态 */
  const removeHtFeeMethodState = (
    mainStorageKeyRaw: string | number,
    rowIdRaw: string | number,
    method: HtFeeMethodType
  ) => setHtFeeMethodState(mainStorageKeyRaw, rowIdRaw, method, null)

  /** 清除指定合同的全部附加费用数据 */
  const removeContractHtFeeData = (contractId: string): boolean => {
    const prefix = `htExtraFee-${contractId}-`
    let changed = false
    for (const key of Object.keys(htFeeMainStates.value)) {
      if (!key.startsWith(prefix)) continue
      delete htFeeMainStates.value[key]
      changed = true
    }
    for (const key of Object.keys(htFeeMethodStates.value)) {
      if (!key.startsWith(prefix)) continue
      delete htFeeMethodStates.value[key]
      changed = true
    }
    return changed
  }

  return {
    htFeeMainStates,
    htFeeMethodStates,
    getHtFeeMainState,
    setHtFeeMainState,
    loadHtFeeMainState,
    removeHtFeeMainState,
    getHtFeeMethodStorageKey,
    getHtFeeMethodState,
    setHtFeeMethodState,
    loadHtFeeMethodState,
    removeHtFeeMethodState,
    removeContractHtFeeData
  }
}, {
  persist: true
})
