/**
 * Mosquito Vue 3 增强版插件
 * 包含全局配置、错误处理、加载状态管理
 */

import { inject, type App, type Plugin } from 'vue'
import MosquitoShareButton from './components/MosquitoShareButton.vue'
import MosquitoPosterCard from './components/MosquitoPosterCard.vue'
import MosquitoLeaderboard from './components/MosquitoLeaderboard.vue'
import './style.css'

// 全局配置接口
export interface MosquitoConfig {
  baseUrl: string
  apiKey: string
  userToken?: string
  timeout?: number
  retryCount?: number
  enableLogging?: boolean
  defaultTheme?: 'light' | 'dark'
  locale?: string
}

// 默认配置
const defaultConfig: MosquitoConfig = {
  baseUrl: '',
  apiKey: '',
  userToken: '',
  timeout: 10000,
  retryCount: 3,
  enableLogging: false,
  defaultTheme: 'light',
  locale: 'zh-CN'
}

// 全局配置实例
let globalConfig = { ...defaultConfig }

// API错误类
export class MosquitoError extends Error {
  constructor(
    message: string,
    public code?: string,
    public statusCode?: number,
    public details?: any
  ) {
    super(message)
    this.name = 'MosquitoError'
  }
}

export interface ApiResponse<T> {
  code: number
  message: string
  data: T
  meta?: {
    pagination?: {
      page: number
      size: number
      total: number
      totalPages: number
      hasNext: boolean
      hasPrevious: boolean
    }
    extra?: Record<string, unknown>
  }
  error?: {
    message?: string
    details?: any
    code?: string
  }
  timestamp?: string
  traceId?: string
}

// 加载状态管理
export class LoadingManager {
  private static loadingStates = new Map<string, boolean>()
  private static callbacks = new Map<string, ((loading: boolean) => void)[]>()

  static setLoading(key: string, loading: boolean) {
    this.loadingStates.set(key, loading)
    
    const callbacks = this.callbacks.get(key) || []
    callbacks.forEach(callback => callback(loading))
  }

  static isLoading(key: string): boolean {
    return this.loadingStates.get(key) || false
  }

  static onLoadingChange(key: string, callback: (loading: boolean) => void) {
    if (!this.callbacks.has(key)) {
      this.callbacks.set(key, [])
    }
    
    this.callbacks.get(key)!.push(callback)
    
    // 返回清理函数
    return () => {
      const callbacks = this.callbacks.get(key)
      if (callbacks) {
        const index = callbacks.indexOf(callback)
        if (index > -1) {
          callbacks.splice(index, 1)
        }
      }
    }
  }
}

// 增强的API客户端
export class EnhancedApiClient {
  private config: MosquitoConfig

  constructor(config: MosquitoConfig) {
    this.config = config
  }

  private async request<T>(
    endpoint: string,
    options: RequestInit = {}
  ): Promise<ApiResponse<T>> {
    const url = `${this.config.baseUrl}${endpoint}`
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), this.config.timeout)

    try {
      const response = await fetch(url, {
        ...options,
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': this.config.apiKey,
          ...(this.config.userToken ? { Authorization: `Bearer ${this.config.userToken}` } : {}),
          ...options.headers,
        },
        signal: controller.signal,
      })

      clearTimeout(timeoutId)

      const payload = await response.json().catch(() => ({}))

      if (!response.ok) {
        const message = payload.message || payload.error?.message || `HTTP ${response.status}: ${response.statusText}`
        throw new MosquitoError(
          message,
          payload.error?.code || payload.code,
          response.status,
          payload.error?.details || payload.error || payload.details
        )
      }

      if (typeof payload?.code === 'number' && payload.code >= 400) {
        throw new MosquitoError(
          payload.message || '请求失败',
          payload.error?.code || payload.code,
          response.status,
          payload.error?.details || payload.error || payload.details
        )
      }

      return payload as ApiResponse<T>
    } catch (error) {
      clearTimeout(timeoutId)
      
      if (error instanceof Error && error.name === 'AbortError') {
        throw new MosquitoError('请求超时', 'TIMEOUT', 408)
      }
      
      throw error
    }
  }

  private async requestData<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    const response = await this.request<T>(endpoint, options)
    return response.data
  }

  async getActivity(id: number): Promise<any> {
    return this.requestData(`/api/v1/activities/${id}`)
  }

  async getActivities(): Promise<any[]> {
    return this.requestData('/api/v1/activities')
  }

  async createActivity(data: any): Promise<any> {
    return this.requestData('/api/v1/activities', {
      method: 'POST',
      body: JSON.stringify(data),
    })
  }

  async getActivityStats(activityId: number): Promise<any> {
    return this.requestData(`/api/v1/activities/${activityId}/stats`)
  }

  async getShareUrl(activityId: number, userId: number, template?: string): Promise<string> {
    const params = new URLSearchParams({
      activityId: activityId.toString(),
      userId: userId.toString(),
      ...(template && { template }),
    })
    
    return this.requestData(`/api/v1/me/share-url?${params}`)
  }

  async getPosterImage(activityId: number, userId: number, template?: string): Promise<Blob> {
    const params = new URLSearchParams({
      activityId: activityId.toString(),
      userId: userId.toString(),
      ...(template && { template }),
    })
    
    const response = await fetch(`${this.config.baseUrl}/api/v1/me/poster/image?${params}`, {
      headers: {
        'X-API-Key': this.config.apiKey,
        ...(this.config.userToken ? { Authorization: `Bearer ${this.config.userToken}` } : {}),
      },
    })
    
    if (!response.ok) {
      throw new MosquitoError('获取海报失败', 'POSTER_ERROR', response.status)
    }
    
    return response.blob()
  }

  async getLeaderboard(
    activityId: number,
    page: number = 0,
    size: number = 20
  ): Promise<any> {
    const params = new URLSearchParams({
      activityId: activityId.toString(),
      page: page.toString(),
      size: size.toString(),
    })
    
    return this.request(`/api/v1/activities/${activityId}/leaderboard?${params}`)
  }

  async getShareMetrics(activityId: number): Promise<any> {
    const params = new URLSearchParams({
      activityId: activityId.toString(),
    })

    return this.requestData(`/api/v1/share/metrics?${params}`)
  }

  async getRewards(activityId: number, userId: number, page: number = 0, size: number = 20): Promise<any[]> {
    const params = new URLSearchParams({
      activityId: activityId.toString(),
      userId: userId.toString(),
      page: page.toString(),
      size: size.toString(),
    })

    return this.requestData(`/api/v1/me/rewards?${params}`)
  }

  async exportLeaderboardCsv(activityId: number): Promise<string> {
    const response = await fetch(`${this.config.baseUrl}/api/v1/activities/${activityId}/leaderboard/export`, {
      headers: {
        'X-API-Key': this.config.apiKey,
        ...(this.config.userToken ? { Authorization: `Bearer ${this.config.userToken}` } : {}),
      },
    })
    
    if (!response.ok) {
      throw new MosquitoError('导出排行榜失败', 'EXPORT_ERROR', response.status)
    }
    
    return response.text()
  }
}

// Vue 插件
const MosquitoEnhancedPlugin: Plugin = {
  install(app: App, options: MosquitoConfig) {
    // 合并配置
    globalConfig = { ...globalConfig, ...options }
    
    // 注册全局属性
    app.config.globalProperties.$mosquito = {
      config: globalConfig,
      apiClient: new EnhancedApiClient(globalConfig),
      loadingManager: LoadingManager,
    }
    
    // 注册全局组件
    app.component('MosquitoShareButton', MosquitoShareButton)
    app.component('MosquitoPosterCard', MosquitoPosterCard)
    app.component('MosquitoLeaderboard', MosquitoLeaderboard)
    
    // 提供组合式API
    app.provide('mosquito', {
      config: globalConfig,
      apiClient: new EnhancedApiClient(globalConfig),
      loadingManager: LoadingManager,
    })
  },
}

// 组合式API
export function useMosquito() {
  const mosquito = inject('mosquito') as any
  
  if (!mosquito) {
    throw new Error('Mosquito plugin is not installed. Please install it with app.use(MosquitoEnhancedPlugin, config)')
  }
  
  const getShareUrl = async (activityId: number, userId: number, template?: string) => {
    const loadingKey = `share-url-${activityId}-${userId}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getShareUrl(activityId, userId, template)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取分享URL失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }
  
  const getPosterImage = async (activityId: number, userId: number, template?: string) => {
    const loadingKey = `poster-image-${activityId}-${userId}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getPosterImage(activityId, userId, template)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取海报失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }
  
  const getLeaderboard = async (activityId: number, page: number = 0, size: number = 20) => {
    const loadingKey = `leaderboard-${activityId}-${page}-${size}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getLeaderboard(activityId, page, size)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取排行榜失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }
  
  const exportLeaderboardCsv = async (activityId: number) => {
    const loadingKey = `export-csv-${activityId}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.exportLeaderboardCsv(activityId)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('导出排行榜失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }
  
  const getActivity = async (id: number) => {
    const loadingKey = `activity-${id}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getActivity(id)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取活动信息失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }

  const getActivities = async () => {
    const loadingKey = 'activities'
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getActivities()
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取活动列表失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }
  
  const createActivity = async (data: any) => {
    const loadingKey = 'create-activity'
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.createActivity(data)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('创建活动失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }

  const getActivityStats = async (activityId: number) => {
    const loadingKey = `activity-stats-${activityId}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getActivityStats(activityId)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取活动统计失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }

  const getShareMetrics = async (activityId: number) => {
    const loadingKey = `share-metrics-${activityId}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getShareMetrics(activityId)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取分享指标失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }

  const getRewards = async (activityId: number, userId: number, page: number = 0, size: number = 20) => {
    const loadingKey = `rewards-${activityId}-${userId}-${page}-${size}`
    LoadingManager.setLoading(loadingKey, true)
    
    try {
      return await mosquito.apiClient.getRewards(activityId, userId, page, size)
    } catch (error) {
      if (globalConfig.enableLogging) {
        console.error('获取奖励失败:', error)
      }
      throw error
    } finally {
      LoadingManager.setLoading(loadingKey, false)
    }
  }
  
  return {
    config: mosquito.config,
    getShareUrl,
    getPosterImage,
    getLeaderboard,
    exportLeaderboardCsv,
    getActivity,
    getActivities,
    createActivity,
    getActivityStats,
    getShareMetrics,
    getRewards,
    loadingManager: LoadingManager,
  }
}

export default MosquitoEnhancedPlugin
export { MosquitoEnhancedPlugin }
