import { DataRelationManager } from '../../core/utils/data-relations'
import { vezaFaker } from '../../core/utils/faker-config'
import type { User, Audio, Playlist } from '../../core/schemas/database'

/**
 * Web service fixtures - MSW handlers and localStorage data
 */
export class WebFixtures {
  private static currentUser: User | null = null
  private static authToken: string | null = null

  /**
   * Initialize web fixtures with authentication
   */
  static async initialize(userId?: string): Promise<void> {
    console.log('🌐 Initializing web fixtures...')
    
    // Get or create current user
    if (userId) {
      this.currentUser = DataRelationManager.getAll().users.get(userId) || null
    }
    
    if (!this.currentUser) {
      // Create a test user
      const { UserGenerator } = await import('../../core/generators/users')
      this.currentUser = UserGenerator.generateTestUser()
      DataRelationManager.registerUser(this.currentUser)
    }
    
    // Generate auth token
    this.authToken = this.generateAuthToken(this.currentUser)
    
    // Seed localStorage
    this.seedLocalStorage()
    
    console.log(`✅ Web fixtures initialized for user: ${this.currentUser.username}`)
  }

  /**
   * Seed localStorage with authentication data
   */
  private static seedLocalStorage(): void {
    if (typeof window === 'undefined') return // Skip in Node.js environment
    
    const authData = {
      access_token: this.authToken,
      refresh_token: this.generateRefreshToken(),
      user: this.currentUser,
      expires_at: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() // 24 hours
    }
    
    // Zustand auth store format
    const authStore = {
      state: {
        user: this.currentUser,
        isAuthenticated: true,
        isLoading: false,
        error: null,
        tokens: {
          access: this.authToken,
          refresh: authData.refresh_token
        }
      },
      version: 0
    }
    
    localStorage.setItem('auth-storage', JSON.stringify(authStore))
    localStorage.setItem('access_token', this.authToken!)
    localStorage.setItem('refresh_token', authData.refresh_token)
    localStorage.setItem('user', JSON.stringify(this.currentUser))
    
    // User preferences
    const preferences = {
      theme: this.currentUser!.preferences.theme,
      language: this.currentUser!.preferences.language,
      notifications: this.currentUser!.preferences.notifications
    }
    
    localStorage.setItem('user-preferences', JSON.stringify(preferences))
    
    // Recent activity
    const recentActivity = this.generateRecentActivity()
    localStorage.setItem('recent-activity', JSON.stringify(recentActivity))
  }

  /**
   * Generate MSW API handlers
   */
  static getMSWHandlers(): any[] {
    const { http, HttpResponse } = require('msw')
    
    return [
      // Authentication endpoints
      http.post('/api/auth/login', async ({ request }: any) => {
        const body = await request.json()
        
        if (body.email === this.currentUser?.email || body.email === 'test@example.com') {
          return HttpResponse.json({
            access_token: this.authToken,
            refresh_token: this.generateRefreshToken(),
            user: this.currentUser,
            expires_in: 86400
          })
        }
        
        return HttpResponse.json(
          { error: 'Invalid credentials' },
          { status: 401 }
        )
      }),

      http.post('/api/auth/register', async ({ request }: any) => {
        const body = await request.json()
        
        // Create new user
        const { UserGenerator } = await import('../../core/generators/users')
        const newUser = UserGenerator.generate({
          role: 'user',
          status: 'active',
          emailVerified: true
        })
        
        // Override with provided data
        newUser.username = body.username
        newUser.email = body.email
        newUser.firstName = body.firstName || body.first_name
        newUser.lastName = body.lastName || body.last_name
        
        return HttpResponse.json({
          access_token: this.generateAuthToken(newUser),
          refresh_token: this.generateRefreshToken(),
          user: newUser,
          expires_in: 86400
        }, { status: 201 })
      }),

      http.post('/api/auth/refresh', async ({ request }: any) => {
        const body = await request.json()
        
        if (body.refresh_token) {
          return HttpResponse.json({
            access_token: this.generateAuthToken(this.currentUser!),
            refresh_token: this.generateRefreshToken(),
            expires_in: 86400
          })
        }
        
        return HttpResponse.json(
          { error: 'Invalid refresh token' },
          { status: 401 }
        )
      }),

      http.post('/api/auth/logout', () => {
        return HttpResponse.json({ message: 'Logged out successfully' })
      }),

      // User endpoints
      http.get('/api/users/me', ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        return HttpResponse.json(this.currentUser)
      }),

      http.put('/api/users/me', async ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        const body = await request.json()
        
        // Update current user
        Object.assign(this.currentUser!, body)
        this.currentUser!.updatedAt = new Date()
        
        return HttpResponse.json(this.currentUser)
      }),

      // Dashboard data
      http.get('/api/dashboard', ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        return HttpResponse.json(this.generateDashboardData())
      }),

      // Audio endpoints
      http.get('/api/tracks', ({ request }: any) => {
        const url = new URL(request.url)
        const limit = parseInt(url.searchParams.get('limit') || '20')
        const offset = parseInt(url.searchParams.get('offset') || '0')
        const genre = url.searchParams.get('genre')
        
        let tracks = Array.from(DataRelationManager.getAll().tracks.values())
        
        if (genre) {
          tracks = tracks.filter(track => track.genre === genre)
        }
        
        const paginatedTracks = tracks.slice(offset, offset + limit)
        
        return HttpResponse.json({
          tracks: paginatedTracks,
          total: tracks.length,
          limit,
          offset,
          hasMore: offset + limit < tracks.length
        })
      }),

      http.get('/api/tracks/:id', ({ params }: any) => {
        const track = DataRelationManager.getAll().tracks.get(params.id)
        if (!track) {
          return HttpResponse.json({ error: 'Track not found' }, { status: 404 })
        }
        
        return HttpResponse.json(track)
      }),

      // Playlist endpoints
      http.get('/api/playlists', ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        const userPlaylists = DataRelationManager.getUserPlaylists(this.currentUser!.id)
        return HttpResponse.json(userPlaylists)
      }),

      http.post('/api/playlists', async ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        const body = await request.json()
        const { AudioGenerator } = await import('../../core/generators/audio')
        
        const playlist = AudioGenerator.generatePlaylist({
          createdById: this.currentUser!.id,
          trackCount: 0,
          visibility: body.visibility || 'private'
        })
        
        // Override with provided data
        playlist.title = body.title
        playlist.description = body.description
        
        DataRelationManager.registerPlaylist(playlist)
        
        return HttpResponse.json(playlist, { status: 201 })
      }),

      // Chat endpoints
      http.get('/api/conversations', ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        const userConversations = DataRelationManager.getUserConversations(this.currentUser!.id)
        return HttpResponse.json(userConversations)
      }),

      http.get('/api/conversations/:id/messages', ({ params, request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        const messages = DataRelationManager.getConversationMessages(params.id)
        return HttpResponse.json(messages)
      }),

      // Search endpoint
      http.get('/api/search', ({ request }: any) => {
        const url = new URL(request.url)
        const query = url.searchParams.get('q')
        const type = url.searchParams.get('type') // 'tracks', 'users', 'playlists', 'all'
        
        if (!query) {
          return HttpResponse.json({ results: [] })
        }
        
        const results = this.performSearch(query, type || undefined)
        return HttpResponse.json(results)
      }),

      // Analytics endpoints
      http.get('/api/analytics/overview', ({ request }: any) => {
        const authHeader = request.headers.get('authorization')
        if (!authHeader || !authHeader.includes(this.authToken!)) {
          return HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })
        }
        
        return HttpResponse.json(this.generateAnalyticsData())
      })
    ]
  }

  /**
   * Generate dashboard data
   */
  private static generateDashboardData(): any {
    const userTracks = DataRelationManager.getUserTracks(this.currentUser!.id)
    const userPlaylists = DataRelationManager.getUserPlaylists(this.currentUser!.id)
    const userConversations = DataRelationManager.getUserConversations(this.currentUser!.id)
    
    return {
      user: this.currentUser,
      stats: {
        tracks: userTracks.length,
        playlists: userPlaylists.length,
        conversations: userConversations.length,
        totalPlays: userTracks.reduce((sum, track) => sum + track.stats.plays, 0),
        totalLikes: userTracks.reduce((sum, track) => sum + track.stats.likes, 0)
      },
      recentTracks: userTracks.slice(0, 5),
      recentPlaylists: userPlaylists.slice(0, 3),
      recentActivity: this.generateRecentActivity(),
      recommendations: this.generateRecommendations()
    }
  }

  /**
   * Generate analytics data
   */
  private static generateAnalyticsData(): any {
    const userTracks = DataRelationManager.getUserTracks(this.currentUser!.id)
    const stats = DataRelationManager.getStatistics()
    
    return {
      overview: {
        totalPlays: userTracks.reduce((sum, track) => sum + track.stats.plays, 0),
        totalLikes: userTracks.reduce((sum, track) => sum + track.stats.likes, 0),
        totalShares: userTracks.reduce((sum, track) => sum + track.stats.shares, 0),
        totalDownloads: userTracks.reduce((sum, track) => sum + track.stats.downloads, 0)
      },
      trends: {
        daily: this.generateTrendData(7),
        weekly: this.generateTrendData(4),
        monthly: this.generateTrendData(12)
      },
      topTracks: userTracks
        .sort((a, b) => b.stats.plays - a.stats.plays)
        .slice(0, 10),
      demographics: {
        byGenre: this.generateGenreStats(userTracks),
        byLocation: this.generateLocationStats(),
        byAge: this.generateAgeStats()
      },
      platform: {
        totalUsers: stats.users,
        totalTracks: stats.tracks,
        totalPlaylists: stats.playlists
      }
    }
  }

  /**
   * Perform search across different content types
   */
  private static performSearch(query: string, type?: string): any {
    const allData = DataRelationManager.getAll()
    const results: any = {
      tracks: [],
      users: [],
      playlists: [],
      total: 0
    }
    
    const searchTerm = query.toLowerCase()
    
    if (!type || type === 'tracks' || type === 'all') {
      results.tracks = Array.from(allData.tracks.values())
        .filter(track => 
          track.title.toLowerCase().includes(searchTerm) ||
          track.artist.toLowerCase().includes(searchTerm) ||
          track.genre.toLowerCase().includes(searchTerm) ||
          track.tags.some(tag => tag.toLowerCase().includes(searchTerm))
        )
        .slice(0, 20)
    }
    
    if (!type || type === 'users' || type === 'all') {
      results.users = Array.from(allData.users.values())
        .filter(user => 
          user.username.toLowerCase().includes(searchTerm) ||
          user.firstName.toLowerCase().includes(searchTerm) ||
          user.lastName.toLowerCase().includes(searchTerm) ||
          (user.displayName && user.displayName.toLowerCase().includes(searchTerm))
        )
        .slice(0, 20)
    }
    
    if (!type || type === 'playlists' || type === 'all') {
      results.playlists = Array.from(allData.playlists.values())
        .filter(playlist => 
          playlist.title.toLowerCase().includes(searchTerm) ||
          (playlist.description && playlist.description.toLowerCase().includes(searchTerm)) ||
          playlist.tags.some(tag => tag.toLowerCase().includes(searchTerm))
        )
        .slice(0, 20)
    }
    
    results.total = results.tracks.length + results.users.length + results.playlists.length
    
    return results
  }

  /**
   * Helper methods
   */
  private static generateAuthToken(user: User): string {
    const header = { alg: 'HS256', typ: 'JWT' }
    const payload = {
      sub: user.id,
      username: user.username,
      email: user.email,
      role: user.role,
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + 86400 // 24 hours
    }
    
    // Simple base64 encoding for mock JWT
    const encodedHeader = btoa(JSON.stringify(header))
    const encodedPayload = btoa(JSON.stringify(payload))
    const signature = btoa(`mock-signature-${user.id}`)
    
    return `${encodedHeader}.${encodedPayload}.${signature}`
  }

  private static generateRefreshToken(): string {
    return `refresh_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  private static generateRecentActivity(): any[] {
    return Array.from({ length: 10 }, () => ({
      id: vezaFaker.string.uuid(),
      type: vezaFaker.helpers.arrayElement(['play', 'like', 'share', 'comment', 'follow']),
      description: vezaFaker.helpers.arrayElement([
        'a écouté un nouveau morceau',
        'a aimé une chanson',
        'a partagé une playlist',
        'a commenté un titre',
        'suit maintenant un artiste'
      ]),
      timestamp: vezaFaker.date.recent({ days: 7 }),
      metadata: {
        trackId: vezaFaker.string.uuid(),
        trackTitle: vezaFaker.music.songTitle()
      }
    }))
  }

  private static generateRecommendations(): any[] {
    const allTracks = Array.from(DataRelationManager.getAll().tracks.values())
    const randomTracks = vezaFaker.helpers.arrayElements(allTracks, 5)
    
    return randomTracks.map(track => ({
      ...track,
      reason: vezaFaker.helpers.arrayElement([
        'Basé sur vos goûts musicaux',
        'Populaire dans votre région',
        'Recommandé par des amis',
        'Tendance cette semaine',
        'Artiste similaire'
      ])
    }))
  }

  private static generateTrendData(periods: number): any[] {
    return Array.from({ length: periods }, (_, i) => ({
      period: i + 1,
      plays: vezaFaker.number.int({ min: 100, max: 1000 }),
      likes: vezaFaker.number.int({ min: 10, max: 100 }),
      shares: vezaFaker.number.int({ min: 5, max: 50 })
    }))
  }

  private static generateGenreStats(tracks: Audio[]): any {
    const genreCounts: Record<string, number> = {}
    tracks.forEach(track => {
      genreCounts[track.genre] = (genreCounts[track.genre] || 0) + 1
    })
    
    return Object.entries(genreCounts).map(([genre, count]) => ({
      genre,
      count,
      percentage: Math.round((count / tracks.length) * 100)
    }))
  }

  private static generateLocationStats(): any[] {
    const locations = ['Paris', 'Lyon', 'Marseille', 'Toulouse', 'Nice']
    return locations.map(location => ({
      location,
      count: vezaFaker.number.int({ min: 50, max: 500 }),
      percentage: vezaFaker.number.int({ min: 5, max: 30 })
    }))
  }

  private static generateAgeStats(): any[] {
    const ageGroups = ['18-24', '25-34', '35-44', '45-54', '55+']
    return ageGroups.map(ageGroup => ({
      ageGroup,
      count: vezaFaker.number.int({ min: 100, max: 1000 }),
      percentage: vezaFaker.number.int({ min: 10, max: 35 })
    }))
  }

  /**
   * Cleanup methods
   */
  static reset(): void {
    this.currentUser = null
    this.authToken = null
    
    if (typeof window !== 'undefined') {
      localStorage.removeItem('auth-storage')
      localStorage.removeItem('access_token')
      localStorage.removeItem('refresh_token')
      localStorage.removeItem('user')
      localStorage.removeItem('user-preferences')
      localStorage.removeItem('recent-activity')
    }
  }

  /**
   * Getters
   */
  static getCurrentUser(): User | null {
    return this.currentUser
  }

  static getAuthToken(): string | null {
    return this.authToken
  }
}