/**
 * Migration Script: Tags → Notebooks with Contextual Labels
 *
 * This script migrates from the flat tags system to the new notebooks system.
 * It creates a default "Labels Migrés" notebook for each user and moves all
 * existing labels to that notebook. Notes remain in "Notes générales" (Inbox).
 *
 * IMPORTANT: This is a NON-BREAKING migration. The existing system continues
 * to work during and after migration.
 *
 * Usage:
 *   npx tsx scripts/migrate-to-notebooks.ts
 *
 * Rollback:
 *   npx tsx scripts/rollback-notebooks.ts
 */

import { prisma } from '../keep-notes/lib/prisma'

interface MigrationStats {
  usersProcessed: number
  notebooksCreated: number
  labelsMigrated: number
  notesAffected: number
  errors: string[]
}

/**
 * Main migration function
 */
async function migrateToNotebooks(): Promise<MigrationStats> {
  console.log('🚀 Starting migration to notebooks...\n')

  const stats: MigrationStats = {
    usersProcessed: 0,
    notebooksCreated: 0,
    labelsMigrated: 0,
    notesAffected: 0,
    errors: [],
  }

  try {
    // Step 1: Get all users
    console.log('📊 Fetching users...')
    const users = await prisma.user.findMany({
      select: {
        id: true,
        name: true,
        email: true,
      },
    })

    if (users.length === 0) {
      console.log('⚠️  No users found. Nothing to migrate.')
      return stats
    }

    console.log(`✅ Found ${users.length} user(s)\n`)

    // Step 2: Process each user
    for (const user of users) {
      console.log(`\n👤 Processing user: ${user.name || user.email} (${user.id})`)

      try {
        // Step 2.1: Check if migration notebook already exists
        const existingNotebook = await prisma.notebook.findFirst({
          where: {
            name: 'Labels Migrés',
            userId: user.id,
          },
        })

        if (existingNotebook) {
          console.log('  ⏭️  Migration notebook already exists, skipping...')
          continue
        }

        // Step 2.2: Create "Labels Migrés" notebook
        console.log('  📁 Creating "Labels Migrés" notebook...')
        const migrationNotebook = await prisma.notebook.create({
          data: {
            id: `migrate-${user.id}`, // Deterministic ID
            name: 'Labels Migrés',
            icon: '📦',
            color: '#9CA3AF', // gray-400
            order: 999, // At the bottom
            userId: user.id,
          },
        })

        stats.notebooksCreated++
        console.log(`  ✅ Created notebook: ${migrationNotebook.id}`)

        // Step 2.3: Migrate all labels for this user
        console.log('  🏷️  Migrating labels...')
        const labels = await prisma.label.findMany({
          where: {
            userId: user.id,
            notebookId: {
              equals: '', // Empty string = not migrated yet
            },
          },
        })

        // Also try with null (in case database has null values)
        const labelsWithNull = await prisma.label.findMany({
          where: {
            userId: user.id,
            notebookId: null,
          },
        })

        // Combine both results (avoid duplicates)
        const allLabels = [...labels]
        for (const label of labelsWithNull) {
          if (!allLabels.find(l => l.id === label.id)) {
            allLabels.push(label)
          }
        }

        if (allLabels.length === 0) {
          console.log('  ℹ️  No labels to migrate')
          continue
        }

        // Update all labels to belong to the migration notebook
        const labelUpdates = allLabels.map((label) =>
          prisma.label.update({
            where: { id: label.id },
            data: { notebookId: migrationNotebook.id },
          })
        )

        await prisma.$transaction(labelUpdates)
        stats.labelsMigrated += allLabels.length
        console.log(`  ✅ Migrated ${allLabels.length} label(s)`)

        // Step 2.4: Count notes that will be affected (information only)
        const noteCount = await prisma.note.count({
          where: { userId: user.id },
        })
        stats.notesAffected += noteCount
        console.log(`  ℹ️  User has ${noteCount} note(s) (will remain in "Notes générales")`)

        stats.usersProcessed++
      } catch (userError) {
        const errorMsg = `Failed to migrate user ${user.id}: ${userError}`
        console.error(`  ❌ ${errorMsg}`)
        stats.errors.push(errorMsg)
      }
    }

    // Summary
    console.log('\n' + '='.repeat(60))
    console.log('✅ Migration complete!\n')
    console.log('📊 Summary:')
    console.log(`  Users processed:   ${stats.usersProcessed}`)
    console.log(`  Notebooks created: ${stats.notebooksCreated}`)
    console.log(`  Labels migrated:   ${stats.labelsMigrated}`)
    console.log(`  Notes affected:    ${stats.notesAffected} (all remain in Inbox)`)

    if (stats.errors.length > 0) {
      console.log(`\n⚠️  Errors: ${stats.errors.length}`)
      stats.errors.forEach((error) => console.log(`  ❌ ${error}`))
    }

    console.log('\n' + '='.repeat(60))
    console.log('\n✨ Migration successful!')
    console.log('\n📌 Next steps:')
    console.log('  1. Test the application to ensure everything works')
    console.log('  2. Users can now organize their notes into notebooks')
    console.log('  3. Users can move labels from "Labels Migrés" to new notebooks')
    console.log('  4. Consider deleting old labels field from Note model after verification\n')

    return stats
  } catch (error) {
    console.error('\n❌ Migration failed:', error)
    throw error
  } finally {
    await prisma.$disconnect()
  }
}

/**
 * Dry-run mode: Show what would happen without making changes
 */
async function dryRunMigration() {
  console.log('🔍 DRY RUN MODE - No changes will be made\n')

  const users = await prisma.user.findMany({
    select: {
      id: true,
      name: true,
      email: true,
    },
  })

  console.log(`Found ${users.length} user(s)\n`)

  for (const user of users) {
    console.log(`\n👤 User: ${user.name || user.email}`)

    const labels = await prisma.label.findMany({
      where: { userId: user.id },
      select: { id: true, name: true },
    })

    const notes = await prisma.note.count({
      where: { userId: user.id },
    })

    console.log(`  Labels: ${labels.length}`)
    console.log(`  Notes: ${notes}`)
    console.log(`  Would create: "Labels Migrés" notebook`)
    console.log(`  Would migrate: ${labels.length} labels`)
  }

  await prisma.$disconnect()
}

// Run migration
const args = process.argv.slice(2)
const isDryRun = args.includes('--dry-run')

if (isDryRun) {
  dryRunMigration()
    .then(() => {
      console.log('\n✅ Dry run complete')
      process.exit(0)
    })
    .catch((error) => {
      console.error('\n❌ Dry run failed:', error)
      process.exit(1)
    })
} else {
  migrateToNotebooks()
    .then(() => {
      console.log('\n✨ All done!')
      process.exit(0)
    })
    .catch((error) => {
      console.error('\n💥 Fatal error:', error)
      process.exit(1)
    })
}
