import { router } from 'expo-router';
import Toast from '@/components/ui/Toast';

import { storage } from './storage';

// 统一的 Token 存储键名（与 lib/auth.ts 保持一致）
export const TOKEN_KEY = 'bestaibest.better-auth.session_token';

interface FetchLoggerOptions {
  enableLogging?: boolean
  logRequest?: boolean
  logResponse?: boolean
  logError?: boolean
}

const defaultOptions: FetchLoggerOptions = {
  enableLogging: __DEV__,
  logRequest: true,
  logResponse: true,
  logError: true,
}

const originalFetch = global.fetch

// 防止重复跳转的标志
let isRedirecting = false

export const createFetchWithLogger = (options: FetchLoggerOptions = {}) => {
  const config = { ...defaultOptions, ...options }

  return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
    const startTime = Date.now()
    const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url
    const method = init?.method || 'GET'

    try {
      // 使用统一的 Token 存储键
      const token = await storage.getItem(TOKEN_KEY)

      // 确保 headers 是一个对象
      const headers: Record<string, string> = {}
      if (init?.headers) {
        if (init.headers instanceof Headers) {
          init.headers.forEach((value, key) => {
            headers[key] = value
          })
        } else if (Array.isArray(init.headers)) {
          init.headers.forEach(([key, value]) => {
            headers[key] = value as string
          })
        } else {
          Object.assign(headers, init.headers)
        }
      }

      // 添加 Bearer Token
      if (token) {
        headers['authorization'] = `Bearer ${token}`
      }

      // 确保 Content-Type 正确设置
      if (method !== 'GET' && method !== 'HEAD' && !headers['Content-Type']) {
        headers['Content-Type'] = 'application/json'
      }

      // 序列化请求体（如果是对象）
      let body = init?.body
      if (body && typeof body === 'object' && !(body instanceof FormData) && !(body instanceof URLSearchParams)) {
        body = JSON.stringify(body)
      }

      const response = await originalFetch(input, {
        ...init,
        headers,
        ...(body !== undefined && { body }),
      })

      // 401 未授权处理
      if (response.status === 401 && !isRedirecting) {
        // 检查是否是登录/注册接口的 401 错误（用户名密码错误）
        const isAuthEndpoint = url.includes('/sign-in/') || url.includes('/sign-up/')

        // 如果是认证接口的 401，不处理，让错误传递到组件
        if (isAuthEndpoint) {
          console.log('🔐 认证接口返回 401，不处理')
          return response
        }

        // 其他接口的 401 才认为是 Token 过期
        console.warn('🔐 401 未授权，跳转到登录页')
        isRedirecting = true

        // 显示 Toast 提示（安全检查）
        try {
          Toast.show('登录已过期，请重新登录')
        } catch (error) {
          console.warn('[Toast] 显示失败:', error)
        }

        // 清除过期 Token
        await storage.removeItem(TOKEN_KEY)

        // 跳转到登录页（使用 replace 避免返回栈问题）
        router.replace('/auth')

        // 延迟重置标志（防止并发请求导致重复跳转）
        setTimeout(() => {
          isRedirecting = false
        }, 1000)
      }

      return response
    } catch (error) {
      const duration = Date.now() - startTime

      if (config.enableLogging && config.logError) {
        console.group(`❌ [FETCH 错误] ${method} ${url}`)
        console.error('📍 URL:', url)
        console.error('🔧 Method:', method)
        console.error('⏱️  Duration:', `${duration}ms`)

        if (init?.headers) {
          console.error('📋 Request Headers:', JSON.stringify(init.headers, null, 2))
        }

        if (init?.body) {
          try {
            const bodyContent = typeof init.body === 'string' ? init.body : JSON.stringify(init.body)
            console.error('📦 Request Body:', bodyContent)
          } catch (e) {
            console.error('📦 Request Body: [无法序列化]')
          }
        }

        console.error('💥 Error Type:', error?.constructor?.name || 'Unknown')
        console.error('💥 Error Message:', error instanceof Error ? error.message : String(error))

        if (error instanceof Error && error.stack) {
          console.error('📚 Stack Trace:', error.stack)
        }

        if (error && typeof error === 'object') {
          console.error('🔍 Error Details:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2))
        }

        console.groupEnd()
      }

      throw error
    }
  }
}

export const fetchWithLogger = createFetchWithLogger()

export const setupGlobalFetchLogger = (options?: FetchLoggerOptions) => {
  const loggedFetch = createFetchWithLogger(options)
  global.fetch = loggedFetch as typeof fetch

  return () => {
    global.fetch = originalFetch
  }
}
