import { ref } from 'vue'

import { fetchNotificationStates, patchNotificationStates } from '../services/notificationStates.js'

const NOTIFICATION_READ_STORAGE_KEY = 'x-financial.topbar.notifications.read'
const NOTIFICATION_HIDDEN_STORAGE_KEY = 'x-financial.topbar.notifications.hidden'

function normalizeNotificationId(value) {
  return String(value || '').trim()
}

function readNotificationIdSet(storageKey) {
  if (typeof window === 'undefined') {
    return new Set()
  }

  try {
    const parsed = JSON.parse(window.localStorage.getItem(storageKey) || '[]')
    return new Set(Array.isArray(parsed) ? parsed.map(normalizeNotificationId).filter(Boolean) : [])
  } catch {
    return new Set()
  }
}

function writeNotificationIdSet(storageKey, values) {
  if (typeof window === 'undefined') {
    return
  }

  window.localStorage.setItem(storageKey, JSON.stringify(Array.from(values).filter(Boolean)))
}

function mergeRemoteStateIntoSets(states, readIds, hiddenIds) {
  for (const item of Array.isArray(states) ? states : []) {
    const id = normalizeNotificationId(item?.notification_id || item?.notificationId)
    if (!id) {
      continue
    }
    if (item.read_at || item.readAt) {
      readIds.add(id)
    }
    if (item.hidden_at || item.hiddenAt) {
      hiddenIds.add(id)
    }
  }
}

function buildContext(item) {
  const target = item?.target || {}
  return {
    kind: String(item?.kind || '').trim(),
    category: String(item?.category || '').trim(),
    target_type: String(target?.type || '').trim()
  }
}

function buildPatch(item, flags) {
  const notificationId = normalizeNotificationId(item?.id || item?.notification_id || item?.notificationId)
  if (!notificationId) {
    return null
  }

  return {
    notification_id: notificationId,
    read: Boolean(flags?.read),
    hidden: Boolean(flags?.hidden),
    context_json: buildContext(item)
  }
}

export function useTopBarNotificationStates() {
  const readNotificationIds = ref(readNotificationIdSet(NOTIFICATION_READ_STORAGE_KEY))
  const hiddenNotificationIds = ref(readNotificationIdSet(NOTIFICATION_HIDDEN_STORAGE_KEY))
  const notificationStateSyncing = ref(false)
  const notificationStateError = ref('')

  function persistLocalSets() {
    writeNotificationIdSet(NOTIFICATION_READ_STORAGE_KEY, readNotificationIds.value)
    writeNotificationIdSet(NOTIFICATION_HIDDEN_STORAGE_KEY, hiddenNotificationIds.value)
  }

  function applyLocalPatch(patch) {
    if (!patch?.notification_id) {
      return
    }
    if (patch.read) {
      readNotificationIds.value.add(patch.notification_id)
    }
    if (patch.hidden) {
      hiddenNotificationIds.value.add(patch.notification_id)
    }
    readNotificationIds.value = new Set(readNotificationIds.value)
    hiddenNotificationIds.value = new Set(hiddenNotificationIds.value)
    persistLocalSets()
  }

  function applyRemoteStates(states) {
    const nextReadIds = new Set(readNotificationIds.value)
    const nextHiddenIds = new Set(hiddenNotificationIds.value)
    mergeRemoteStateIntoSets(states, nextReadIds, nextHiddenIds)
    readNotificationIds.value = nextReadIds
    hiddenNotificationIds.value = nextHiddenIds
    persistLocalSets()
  }

  async function loadNotificationStates() {
    notificationStateSyncing.value = true
    notificationStateError.value = ''
    try {
      applyRemoteStates(await fetchNotificationStates())
    } catch (error) {
      notificationStateError.value = error?.message || '通知状态同步失败'
    } finally {
      notificationStateSyncing.value = false
    }
  }

  async function syncNotificationPatches(patches) {
    const normalizedPatches = (Array.isArray(patches) ? patches : []).filter(Boolean)
    if (!normalizedPatches.length) {
      return
    }

    normalizedPatches.forEach(applyLocalPatch)
    notificationStateError.value = ''
    try {
      applyRemoteStates(await patchNotificationStates(normalizedPatches))
    } catch (error) {
      notificationStateError.value = error?.message || '通知状态同步失败'
    }
  }

  function isNotificationHidden(id) {
    return hiddenNotificationIds.value.has(normalizeNotificationId(id))
  }

  function isNotificationRead(id) {
    return readNotificationIds.value.has(normalizeNotificationId(id))
  }

  function markNotificationStateRead(item) {
    return markNotificationStatesRead([item])
  }

  function markNotificationStatesRead(items) {
    const patches = (Array.isArray(items) ? items : [])
      .map((item) => buildPatch(item, { read: true, hidden: false }))
      .filter(Boolean)
    return syncNotificationPatches(patches)
  }

  function hideNotificationStates(items) {
    const patches = (Array.isArray(items) ? items : [])
      .map((item) => buildPatch(item, { read: true, hidden: true }))
      .filter(Boolean)
    return syncNotificationPatches(patches)
  }

  return {
    hiddenNotificationIds,
    readNotificationIds,
    notificationStateSyncing,
    notificationStateError,
    hideNotificationStates,
    isNotificationHidden,
    isNotificationRead,
    loadNotificationStates,
    markNotificationStateRead,
    markNotificationStatesRead
  }
}
