import { DataRelationManager } from '../../core/utils/data-relations'
import { UserGenerator } from '../../core/generators/users'
import { AudioGenerator } from '../../core/generators/audio'
import { ConversationGenerator } from '../../core/generators/conversations'
import { vezaFaker } from '../../core/utils/faker-config'
import type { User, Audio, Playlist, Conversation } from '../../core/schemas/database'

/**
 * New User Onboarding Scenario
 * 
 * Simulates a complete user journey from registration to first meaningful interactions
 */
export interface OnboardingScenarioContext {
  user: User
  initialData: {
    recommendedTracks: Audio[]
    welcomePlaylist: Playlist
    welcomeConversation: Conversation
    onboardingSteps: OnboardingStep[]
  }
  expectedBehavior: {
    shouldSeeWelcomeMessage: boolean
    shouldHaveEmptyLibrary: boolean
    shouldReceiveRecommendations: boolean
    shouldJoinWelcomeChannel: boolean
    shouldCompleteOnboarding: boolean
  }
  testData: {
    loginCredentials: { email: string; password: string }
    profileData: Partial<User>
    firstActions: UserAction[]
  }
}

export interface OnboardingStep {
  id: string
  title: string
  description: string
  type: 'welcome' | 'profile' | 'preferences' | 'discovery' | 'social'
  isRequired: boolean
  isCompleted: boolean
  data?: any
}

export interface UserAction {
  type: 'play_track' | 'like_track' | 'create_playlist' | 'follow_user' | 'send_message'
  timestamp: Date
  data: any
  expectedResult: string
}

/**
 * New User Onboarding Scenario Generator
 */
export class NewUserOnboardingScenario {
  /**
   * Generate complete onboarding scenario
   */
  static async setup(): Promise<OnboardingScenarioContext> {
    console.log('🎯 Setting up new user onboarding scenario...')
    
    // Generate new user
    const user = UserGenerator.generate({
      role: 'user',
      status: 'active',
      emailVerified: false, // Will be verified during onboarding
      withAvatar: false, // Will be set during profile completion
      withBio: false,
      withStats: false, // New user has no activity
    })
    
    // Override stats for new user
    user.stats = {
      tracksUploaded: 0,
      playlistsCreated: 0,
      followersCount: 0,
      followingCount: 0,
      totalPlays: 0,
    }
    
    DataRelationManager.registerUser(user)
    
    // Generate initial recommendations based on popular content
    const allTracks = Array.from(DataRelationManager.getAll().tracks.values())
    const recommendedTracks = this.generateRecommendations(allTracks, user)
    
    // Create welcome playlist
    const welcomePlaylist = AudioGenerator.generatePlaylist({
      createdById: 'system', // System-generated playlist
      trackCount: 10,
      visibility: 'public',
      theme: 'random'
    })
    welcomePlaylist.title = 'Bienvenue sur Veza !'
    welcomePlaylist.description = 'Une sélection de morceaux populaires pour découvrir la plateforme'
    welcomePlaylist.trackIds = recommendedTracks.slice(0, 10).map(t => t.id)
    
    DataRelationManager.registerPlaylist(welcomePlaylist)
    
    // Create welcome conversation (general channel)
    const welcomeConversation = ConversationGenerator.generateConversation({
      type: 'channel',
      participantIds: [user.id, 'system'], // User + system/moderators
      messageCount: 5, // Few welcome messages
      timeSpan: 'recent'
    })
    welcomeConversation.name = 'Bienvenue'
    welcomeConversation.description = 'Canal d\'accueil pour les nouveaux utilisateurs'
    welcomeConversation.isPrivate = false
    
    DataRelationManager.registerConversation(welcomeConversation)
    
    // Generate onboarding steps
    const onboardingSteps = this.generateOnboardingSteps(user)
    
    // Generate first user actions
    const firstActions = this.generateFirstUserActions(user, recommendedTracks)
    
    const context: OnboardingScenarioContext = {
      user,
      initialData: {
        recommendedTracks,
        welcomePlaylist,
        welcomeConversation,
        onboardingSteps
      },
      expectedBehavior: {
        shouldSeeWelcomeMessage: true,
        shouldHaveEmptyLibrary: true,
        shouldReceiveRecommendations: true,
        shouldJoinWelcomeChannel: true,
        shouldCompleteOnboarding: true
      },
      testData: {
        loginCredentials: {
          email: user.email,
          password: 'TestPassword123!'
        },
        profileData: {
          firstName: user.firstName,
          lastName: user.lastName,
          bio: 'Nouveau sur Veza, passionné de musique !',
          location: user.location,
          preferences: {
            ...user.preferences,
            notifications: {
              email: true,
              push: true,
              desktop: false
            }
          }
        },
        firstActions
      }
    }
    
    console.log('✅ New user onboarding scenario setup complete')
    return context
  }
  
  /**
   * Generate multiple onboarding scenarios for different user types
   */
  static async setupBatch(count: number = 5): Promise<OnboardingScenarioContext[]> {
    const scenarios: OnboardingScenarioContext[] = []
    
    for (let i = 0; i < count; i++) {
      const scenario = await this.setup()
      scenarios.push(scenario)
    }
    
    return scenarios
  }
  
  /**
   * Simulate user completing onboarding steps
   */
  static simulateOnboardingCompletion(context: OnboardingScenarioContext): {
    completedSteps: OnboardingStep[]
    updatedUser: User
    generatedContent: {
      firstPlaylist: Playlist
      profileUpdates: Partial<User>
      firstInteractions: UserAction[]
    }
  } {
    console.log(`🎮 Simulating onboarding completion for user: ${context.user.username}`)
    
    // Mark steps as completed
    const completedSteps = context.initialData.onboardingSteps.map(step => ({
      ...step,
      isCompleted: true,
      data: this.generateStepCompletionData(step, context.user)
    }))
    
    // Update user profile
    const updatedUser: User = {
      ...context.user,
      ...context.testData.profileData,
      emailVerified: true,
      avatar: vezaFaker.image.avatar(),
      isVerified: false, // New users aren't verified yet
      preferences: {
        ...context.user.preferences,
        ...context.testData.profileData.preferences
      },
      updatedAt: new Date()
    }
    
    // Create user's first playlist
    const firstPlaylist = AudioGenerator.generatePlaylist({
      createdById: context.user.id,
      trackCount: 5,
      visibility: 'private',
      theme: 'random'
    })
    firstPlaylist.title = 'Ma première playlist'
    firstPlaylist.description = 'Mes premiers coups de cœur sur Veza'
    firstPlaylist.trackIds = context.initialData.recommendedTracks.slice(0, 5).map(t => t.id)
    
    DataRelationManager.registerPlaylist(firstPlaylist)
    
    // Update user stats
    updatedUser.stats.playlistsCreated = 1
    
    // Generate first interactions
    const firstInteractions = this.generateFirstInteractions(context)
    
    console.log('✅ Onboarding completion simulation complete')
    
    return {
      completedSteps,
      updatedUser,
      generatedContent: {
        firstPlaylist,
        profileUpdates: context.testData.profileData,
        firstInteractions
      }
    }
  }
  
  /**
   * Validate onboarding scenario expectations
   */
  static validateScenario(context: OnboardingScenarioContext): {
    isValid: boolean
    passedChecks: string[]
    failedChecks: string[]
    warnings: string[]
  } {
    const passedChecks: string[] = []
    const failedChecks: string[] = []
    const warnings: string[] = []
    
    // Check user data
    if (context.user.stats.tracksUploaded === 0) {
      passedChecks.push('New user has no uploaded tracks')
    } else {
      failedChecks.push('New user should not have uploaded tracks')
    }
    
    if (context.user.stats.playlistsCreated === 0) {
      passedChecks.push('New user has no created playlists')
    } else {
      failedChecks.push('New user should not have created playlists initially')
    }
    
    if (!context.user.emailVerified) {
      passedChecks.push('New user email is not verified initially')
    } else {
      warnings.push('New user email should not be verified initially')
    }
    
    // Check recommendations
    if (context.initialData.recommendedTracks.length > 0) {
      passedChecks.push('Recommendations are provided')
    } else {
      failedChecks.push('No recommendations provided for new user')
    }
    
    // Check welcome content
    if (context.initialData.welcomePlaylist) {
      passedChecks.push('Welcome playlist exists')
    } else {
      failedChecks.push('Welcome playlist not created')
    }
    
    if (context.initialData.welcomeConversation) {
      passedChecks.push('Welcome conversation exists')
    } else {
      failedChecks.push('Welcome conversation not created')
    }
    
    // Check onboarding steps
    const requiredSteps = context.initialData.onboardingSteps.filter(s => s.isRequired)
    if (requiredSteps.length >= 3) {
      passedChecks.push('Sufficient required onboarding steps')
    } else {
      failedChecks.push('Not enough required onboarding steps')
    }
    
    // Check first actions
    if (context.testData.firstActions.length > 0) {
      passedChecks.push('First user actions defined')
    } else {
      warnings.push('No first user actions defined')
    }
    
    return {
      isValid: failedChecks.length === 0,
      passedChecks,
      failedChecks,
      warnings
    }
  }
  
  /**
   * Private helper methods
   */
  private static generateRecommendations(allTracks: Audio[], user: User): Audio[] {
    // For new users, recommend popular tracks across different genres
    const popularTracks = allTracks
      .sort((a, b) => b.stats.plays - a.stats.plays)
      .slice(0, 50)
    
    // Select diverse genres
    const genreGroups = this.groupTracksByGenre(popularTracks)
    const recommendations: Audio[] = []
    
    // Take 2-3 tracks from each popular genre
    Object.entries(genreGroups).forEach(([genre, tracks]) => {
      const genreTracks = vezaFaker.helpers.arrayElements(tracks, Math.min(3, tracks.length))
      recommendations.push(...genreTracks)
    })
    
    // Shuffle and limit to 20 recommendations
    return vezaFaker.helpers.shuffle(recommendations).slice(0, 20)
  }
  
  private static groupTracksByGenre(tracks: Audio[]): Record<string, Audio[]> {
    return tracks.reduce((groups, track) => {
      if (!groups[track.genre]) {
        groups[track.genre] = []
      }
      groups[track.genre]!.push(track)
      return groups
    }, {} as Record<string, Audio[]>)
  }
  
  private static generateOnboardingSteps(user: User): OnboardingStep[] {
    return [
      {
        id: 'welcome',
        title: 'Bienvenue sur Veza !',
        description: 'Découvrez votre nouvelle plateforme musicale',
        type: 'welcome',
        isRequired: true,
        isCompleted: false,
        data: {
          welcomeMessage: `Salut ${user.firstName} ! Bienvenue dans la communauté Veza.`,
          features: ['streaming', 'playlists', 'chat', 'discovery']
        }
      },
      {
        id: 'email_verification',
        title: 'Vérifiez votre email',
        description: 'Confirmez votre adresse email pour sécuriser votre compte',
        type: 'profile',
        isRequired: true,
        isCompleted: false,
        data: {
          email: user.email,
          verificationCode: vezaFaker.string.numeric(6)
        }
      },
      {
        id: 'profile_setup',
        title: 'Complétez votre profil',
        description: 'Ajoutez une photo et une bio pour vous présenter',
        type: 'profile',
        isRequired: false,
        isCompleted: false,
        data: {
          suggestedBio: 'Passionné de musique, nouveau sur Veza !',
          avatarOptions: [
            vezaFaker.image.avatar(),
            vezaFaker.image.avatar(),
            vezaFaker.image.avatar()
          ]
        }
      },
      {
        id: 'music_preferences',
        title: 'Choisissez vos genres préférés',
        description: 'Aidez-nous à vous recommander de la musique',
        type: 'preferences',
        isRequired: false,
        isCompleted: false,
        data: {
          availableGenres: ['rock', 'pop', 'jazz', 'electronic', 'hip-hop', 'classical'],
          maxSelections: 5
        }
      },
      {
        id: 'first_playlist',
        title: 'Créez votre première playlist',
        description: 'Organisez vos morceaux préférés',
        type: 'discovery',
        isRequired: false,
        isCompleted: false,
        data: {
          suggestedName: 'Mes découvertes',
          suggestedTracks: 5
        }
      },
      {
        id: 'join_community',
        title: 'Rejoignez la communauté',
        description: 'Participez aux discussions et découvrez de nouveaux artistes',
        type: 'social',
        isRequired: false,
        isCompleted: false,
        data: {
          recommendedChannels: ['Bienvenue', 'Découvertes', 'Feedback'],
          welcomeMessage: 'Salut tout le monde ! Je suis nouveau sur Veza 👋'
        }
      }
    ]
  }
  
  private static generateFirstUserActions(user: User, tracks: Audio[]): UserAction[] {
    const actions: UserAction[] = []
    const now = new Date()
    
    // First action: play a recommended track
    const firstTrack = tracks[0]
    if (!firstTrack) return actions
    actions.push({
      type: 'play_track',
      timestamp: new Date(now.getTime() + 5 * 60 * 1000), // 5 minutes after registration
      data: {
        trackId: firstTrack.id,
        duration: Math.min(firstTrack.metadata.duration, 30), // Listen for 30 seconds
        completion: 0.1
      },
      expectedResult: 'Track plays successfully, user engagement recorded'
    })
    
    // Second action: like the track
    actions.push({
      type: 'like_track',
      timestamp: new Date(now.getTime() + 6 * 60 * 1000),
      data: {
        trackId: firstTrack.id
      },
      expectedResult: 'Track is added to user likes, recommendation algorithm updated'
    })
    
    // Third action: create first playlist
    actions.push({
      type: 'create_playlist',
      timestamp: new Date(now.getTime() + 10 * 60 * 1000),
      data: {
        name: 'Ma première playlist',
        description: 'Mes premiers coups de cœur',
        trackIds: tracks.slice(0, 3).map(t => t.id),
        visibility: 'private'
      },
      expectedResult: 'Playlist created, user stats updated'
    })
    
    // Fourth action: send welcome message
    actions.push({
      type: 'send_message',
      timestamp: new Date(now.getTime() + 15 * 60 * 1000),
      data: {
        conversationId: 'welcome-channel',
        content: 'Salut tout le monde ! Je découvre Veza, c\'est génial ! 🎵',
        type: 'text'
      },
      expectedResult: 'Message sent to welcome channel, community engagement started'
    })
    
    return actions
  }
  
  private static generateStepCompletionData(step: OnboardingStep, user: User): any {
    switch (step.type) {
      case 'welcome':
        return {
          completedAt: new Date(),
          timeSpent: vezaFaker.number.int({ min: 30, max: 120 }), // seconds
          interacted: true
        }
      
      case 'profile':
        if (step.id === 'email_verification') {
          return {
            verifiedAt: new Date(),
            verificationCode: step.data?.verificationCode,
            attempts: 1
          }
        }
        return {
          avatarSelected: vezaFaker.image.avatar(),
          bioAdded: true,
          completedAt: new Date()
        }
      
      case 'preferences':
        return {
          selectedGenres: vezaFaker.helpers.arrayElements(
            step.data?.availableGenres || [],
            vezaFaker.number.int({ min: 2, max: 5 })
          ),
          completedAt: new Date()
        }
      
      case 'discovery':
        return {
          playlistCreated: true,
          tracksAdded: vezaFaker.number.int({ min: 3, max: 8 }),
          completedAt: new Date()
        }
      
      case 'social':
        return {
          channelsJoined: vezaFaker.helpers.arrayElements(
            step.data?.recommendedChannels || [],
            vezaFaker.number.int({ min: 1, max: 3 })
          ),
          messageSent: true,
          completedAt: new Date()
        }
      
      default:
        return {
          completedAt: new Date(),
          success: true
        }
    }
  }
  
  private static generateFirstInteractions(context: OnboardingScenarioContext): UserAction[] {
    const interactions: UserAction[] = []
    const now = new Date()
    
    // Simulate realistic user behavior over first hour
    const timeOffsets = [300, 600, 900, 1200, 1800, 2400, 3000, 3600] // seconds
    
    timeOffsets.forEach((offset, index) => {
      const actionTypes = ['play_track', 'like_track', 'create_playlist', 'follow_user', 'send_message']
      const actionType = vezaFaker.helpers.arrayElement(actionTypes) as any
      
      let data: any = {}
      let expectedResult = ''
      
      switch (actionType) {
        case 'play_track':
          const track = vezaFaker.helpers.arrayElement(context.initialData.recommendedTracks)
          data = {
            trackId: track.id,
            duration: vezaFaker.number.int({ min: 15, max: track.metadata.duration }),
            completion: vezaFaker.number.float({ min: 0.1, max: 1.0 })
          }
          expectedResult = 'Track playback initiated, listening stats updated'
          break
          
        case 'like_track':
          data = {
            trackId: vezaFaker.helpers.arrayElement(context.initialData.recommendedTracks).id
          }
          expectedResult = 'Track liked, user preferences updated'
          break
          
        case 'send_message':
          data = {
            conversationId: context.initialData.welcomeConversation.id,
            content: vezaFaker.chat.messageContent(),
            type: 'text'
          }
          expectedResult = 'Message sent, conversation activity updated'
          break
          
        default:
          data = { action: actionType }
          expectedResult = `${actionType} completed successfully`
      }
      
      interactions.push({
        type: actionType,
        timestamp: new Date(now.getTime() + offset * 1000),
        data,
        expectedResult
      })
    })
    
    return interactions
  }
}

/**
 * Export scenario configuration
 */
export const NEW_USER_ONBOARDING_SCENARIO = {
  name: 'New User Onboarding',
  description: 'Complete user journey from registration to first meaningful platform interactions',
  duration: '1 hour',
  complexity: 'medium',
  userTypes: ['new_user'],
  expectedOutcomes: [
    'User successfully completes registration',
    'Email verification completed',
    'Profile setup completed',
    'First playlist created',
    'Community engagement initiated',
    'Recommendation system activated'
  ],
  testCoverage: [
    'authentication_flow',
    'profile_management',
    'content_discovery',
    'playlist_creation',
    'social_features',
    'notification_system'
  ]
}