// lib/utils.ts
import type { ClassValue } from 'clsx'
import clsx from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

/**
 * 安全地访问 sessionStorage
 * 在无痕模式或存储被禁用时返回 null，避免抛出错误
 */
export function safeSessionStorageGetItem(key: string): string | null {
  try {
    return sessionStorage.getItem(key)
  }
  catch {
    // 在无痕模式或存储被禁用时，静默失败
    return null
  }
}

/**
 * 安全地设置 sessionStorage
 * 在无痕模式或存储被禁用时静默失败
 */
export function safeSessionStorageSetItem(key: string, value: string): void {
  try {
    sessionStorage.setItem(key, value)
  }
  catch {
    // 在无痕模式或存储被禁用时，静默失败
  }
}

/**
 * 安全地删除 sessionStorage
 * 在无痕模式或存储被禁用时静默失败
 */
export function safeSessionStorageRemoveItem(key: string): void {
  try {
    sessionStorage.removeItem(key)
  }
  catch {
    // 在无痕模式或存储被禁用时，静默失败
  }
}

/**
 * 安全地访问 localStorage
 * 在无痕模式或存储被禁用时返回 null，避免抛出错误
 */
export function safeLocalStorageGetItem(key: string): string | null {
  try {
    return localStorage.getItem(key)
  }
  catch {
    // 在无痕模式或存储被禁用时，静默失败
    return null
  }
}

/**
 * 安全地设置 localStorage
 * 在无痕模式或存储被禁用时静默失败
 */
export function safeLocalStorageSetItem(key: string, value: string): void {
  try {
    localStorage.setItem(key, value)
  }
  catch {
    // 在无痕模式或存储被禁用时，静默失败
  }
}

const USER_ROLES_STORAGE_KEY = '__USER_ROLES__'

/**
 * 从路由获取 userRoles 并存储到 localStorage
 * @returns 返回获取到的 userRoles 数组
 */
function getQueryBeforeSecondQuestion(): string {
  try {
    const href = window.location.href || ''
    const firstQuestionIndex = href.indexOf('?')
    if (firstQuestionIndex === -1)
      return ''

    const queryCandidate = href.slice(firstQuestionIndex + 1)
    const secondQuestionIndex = queryCandidate.indexOf('?')
    const sliced = secondQuestionIndex === -1
      ? queryCandidate
      : queryCandidate.slice(0, secondQuestionIndex)

    // 兼容后端返回 `&&` 作为分隔符的情况，统一替换成单个 `&`
    return sliced.replace(/&{2,}/g, '&')
  }
  catch {
    return ''
  }
}

/**
 * 从路径中提取查询字符串（支持参数作为路径一部分的情况）
 * 例如：/home/userRoles=00&&userRoles=01&&loginCode=2392039
 * @returns 返回查询字符串，格式为 key=value&key=value
 */
function extractQueryStringFromPath(): string {
  try {
    const pathname = window.location.pathname || ''

    // 如果路径中包含 = 符号，说明参数可能作为路径的一部分
    if (pathname.includes('=')) {
      // 找到最后一个 / 之后的内容
      // 例如：/home/userRoles=00&&userRoles=01 提取 userRoles=00&&userRoles=01
      const lastSlashIndex = pathname.lastIndexOf('/')
      if (lastSlashIndex !== -1 && lastSlashIndex < pathname.length - 1) {
        const pathAfterLastSlash = pathname.substring(lastSlashIndex + 1)
        if (pathAfterLastSlash.includes('=')) {
          // 兼容 && 作为分隔符的情况，统一替换成单个 &
          return pathAfterLastSlash.replace(/&{2,}/g, '&')
        }
      }
    }

    return ''
  }
  catch {
    return ''
  }
}

/**
 * 从路由获取 userRoles（不存储到 localStorage）
 * 支持两种格式：
 * 1. 标准查询参数：/home?userRoles=00&userRoles=01
 * 2. 路径参数：/home/userRoles=00&&userRoles=01
 * @returns 返回获取到的 userRoles 数组
 */
export function getUserRolesFromRoute(): string[] {
  try {
    // 首先尝试从标准查询参数获取
    const sanitizedSearch = getQueryBeforeSecondQuestion()
    // 兜底：兼容 && 拼接
    const normalizedSearch = (sanitizedSearch || window.location.search).replace(/&{2,}/g, '&')
    let searchParams = new URLSearchParams(normalizedSearch)
    let rolesFromRepeatedKeys = searchParams.getAll('userRoles').filter(Boolean)
    let userRoles: string[] = []

    // 如果从标准查询参数中找到了，直接返回
    if (rolesFromRepeatedKeys.length) {
      userRoles = Array.from(new Set(rolesFromRepeatedKeys))
      // 首次获取到时写入 sessionStorage 兜底
      try {
        safeSessionStorageSetItem(USER_ROLES_STORAGE_KEY, JSON.stringify(userRoles))
      }
      catch {
        // 无痕模式或被禁用时静默
      }
      return userRoles
    }

    // 如果标准查询参数中没有，尝试从路径中解析
    const pathQueryString = extractQueryStringFromPath()
    if (pathQueryString) {
      // 将路径参数转换为标准查询字符串格式
      // 例如：userRoles=00&&userRoles=01 转换为 userRoles=00&userRoles=01
      const normalizedQuery = pathQueryString.replace(/&{2,}/g, '&')
      searchParams = new URLSearchParams(normalizedQuery)
      rolesFromRepeatedKeys = searchParams.getAll('userRoles').filter(Boolean)

      if (rolesFromRepeatedKeys.length) {
        userRoles = Array.from(new Set(rolesFromRepeatedKeys))
        try {
          safeSessionStorageSetItem(USER_ROLES_STORAGE_KEY, JSON.stringify(userRoles))
        }
        catch {
        }
        return userRoles
      }

      // 尝试逗号分隔的格式
      const commaSeparated = searchParams.get('userRoles')
      if (commaSeparated) {
        const roles = commaSeparated
          .split(',')
          .map(role => role.trim())
          .filter(Boolean)
        if (roles.length) {
          userRoles = Array.from(new Set(roles))
          try {
            safeSessionStorageSetItem(USER_ROLES_STORAGE_KEY, JSON.stringify(userRoles))
          }
          catch {
          }
          return userRoles
        }
      }
    }

    // 最后尝试从标准查询参数中获取逗号分隔的格式
    if (!userRoles.length) {
      const commaSeparated = searchParams.get('userRoles')
      if (commaSeparated) {
        const roles = commaSeparated
          .split(',')
          .map(role => role.trim())
          .filter(Boolean)
        if (roles.length) {
          userRoles = Array.from(new Set(roles))
          try {
            safeSessionStorageSetItem(USER_ROLES_STORAGE_KEY, JSON.stringify(userRoles))
          }
          catch {
          }
        }
      }
    }

    // 兜底：从 sessionStorage 读取（同一标签页有效）
    if (!userRoles.length) {
      try {
        const stored = safeSessionStorageGetItem(USER_ROLES_STORAGE_KEY)
        if (stored) {
          const parsed = JSON.parse(stored)
          if (Array.isArray(parsed) && parsed.length)
            return Array.from(new Set(parsed.filter(Boolean)))
        }
      }
      catch {
        // 静默
      }
    }

    return userRoles
  }
  catch {
    return []
  }
}

/**
 * @deprecated 已废弃，请使用 getUserRolesFromRoute
 * 从路由获取 userRoles 并存储到 localStorage
 * @returns 返回获取到的 userRoles 数组
 */
export function getUserRolesFromRouteAndStore(): string[] {
  const userRoles = getUserRolesFromRoute()

  // 如果获取到了 userRoles，存储到 localStorage（向后兼容）
  if (userRoles.length > 0) {
    safeLocalStorageSetItem(USER_ROLES_STORAGE_KEY, JSON.stringify(userRoles))
  }

  return userRoles
}

/**
 * 从 localStorage 读取 userRoles
 * @returns 返回 userRoles 数组，如果没有则返回空数组
 */
export function getUserRolesFromStorage(): string[] {
  try {
    const stored = safeLocalStorageGetItem(USER_ROLES_STORAGE_KEY)
    if (stored) {
      const userRoles = JSON.parse(stored)
      if (Array.isArray(userRoles) && userRoles.length > 0) {
        return userRoles
      }
    }
  }
  catch {
    // 静默失败，返回空数组
  }
  return []
}

/**
 * 获取 userRoles（从路由获取，确保使用最新的路由参数）
 * 这是推荐的统一方法，确保调用 fetchToolList 时能获取到正确的 userRoles
 * @returns 返回 userRoles 数组，如果没有则返回空数组
 */
export function getUserRolesForApi(): string[] {
  // 直接从路由中获取 userRoles（路由参数是唯一真实来源）
  return getUserRolesFromRoute()
}

/**
 * 等待 token 就绪，确保登录接口返回后才继续
 * @param maxWaitTime 最大等待时间（毫秒），默认 3000ms
 * @returns Promise<boolean> 返回 true 表示 token 已就绪，false 表示超时
 */
export async function waitForToken(maxWaitTime = 3000): Promise<boolean> {
  const startTime = Date.now()
  let initialToken = ''
  // 先获取初始 token 值
  try {
    const initialTokenStr = window.localStorage.getItem('__TOKEN__') || '""'
    initialToken = JSON.parse(initialTokenStr) || ''
  }
  catch {
    initialToken = ''
  }

  // 如果初始没有 token，等待 token 出现（从无到有，说明登录完成）
  if (!initialToken) {
    while (Date.now() - startTime < maxWaitTime) {
      const tokenStr = window.localStorage.getItem('__TOKEN__') || '""'
      let token = ''
      try {
        token = JSON.parse(tokenStr) || ''
      }
      catch {
        token = ''
      }
      if (token) {
        // token 从无到有，说明登录完成，再等待一小段时间确保写入完成
        await new Promise(resolve => setTimeout(resolve, 200))
        return true
      }
      // 等待 100ms 后再次检查
      await new Promise(resolve => setTimeout(resolve, 100))
    }
    return false
  }

  // 如果初始有 token，可能是旧 token 或新 token
  // 等待一小段时间，确保登录流程有足够时间完成（登录接口可能会更新 token）
  // 同时监听 token 变化
  let tokenChanged = false
  const checkTokenChange = () => {
    try {
      const currentTokenStr = window.localStorage.getItem('__TOKEN__') || '""'
      const currentToken = JSON.parse(currentTokenStr) || ''
      if (currentToken && currentToken !== initialToken) {
        tokenChanged = true
      }
    }
    catch {
      // 忽略解析错误
    }
  }

  // 监听 storage 事件（跨标签页）
  window.addEventListener('storage', checkTokenChange)
  // 轮询检查（同标签页）
  const interval = setInterval(checkTokenChange, 100)

  // 等待最多 1 秒，检测 token 是否变化
  const waitForChange = new Promise<void>((resolve) => {
    setTimeout(() => {
      window.removeEventListener('storage', checkTokenChange)
      clearInterval(interval)
      resolve()
    }, 1000)
  })
  await waitForChange

  // 如果 token 变化了，说明登录完成，再等待一小段时间确保写入完成
  if (tokenChanged) {
    await new Promise(resolve => setTimeout(resolve, 200))
    return true
  }

  // 如果 token 没有变化，可能是已经登录完成，但为了确保登录流程完成，再等待一小段时间
  await new Promise(resolve => setTimeout(resolve, 300))
  return true
}
