#!/usr/bin/env node
/**
 * Migration script - Migrate data from JSON files to database
 */

const fs = require('fs');
const path = require('path');
const { initDatabase, getDatabase, closeDatabase } = require('../src/database/connection');
const { initEncryption } = require('../src/utils/encryption');
const userRepo = require('../src/repositories/userRepository');

const DATA_ROOT = process.env.CHAT_DATA_ROOT || path.join(__dirname, '..', '.data');
const DATABASE_PATH = process.env.DATABASE_PATH || path.join(DATA_ROOT, 'shopify_ai.db');
const DATABASE_ENCRYPTION_KEY = process.env.DATABASE_ENCRYPTION_KEY;

const USERS_FILE = path.join(DATA_ROOT, 'users.json');
const SESSIONS_FILE = path.join(DATA_ROOT, 'user-sessions.json');
const AFFILIATES_FILE = path.join(DATA_ROOT, 'affiliates.json');

async function loadJsonFile(filePath, defaultValue = []) {
  try {
    const data = fs.readFileSync(filePath, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    if (error.code === 'ENOENT') {
      console.log(`  File not found: ${filePath}, using default`);
      return defaultValue;
    }
    throw error;
  }
}

async function migrateUsers() {
  console.log('\n📦 Migrating users...');
  
  const users = await loadJsonFile(USERS_FILE, []);
  console.log(`  Found ${users.length} users in JSON`);
  
  if (users.length === 0) {
    console.log('  No users to migrate');
    return { success: 0, failed: 0 };
  }
  
  let success = 0;
  let failed = 0;
  
  for (const user of users) {
    try {
      // Check if user already exists
      const existing = userRepo.getUserById(user.id);
      if (existing) {
        console.log(`  Skipping existing user: ${user.email}`);
        success++;
        continue;
      }
      
      // Create user in database
      userRepo.createUser({
        id: user.id,
        email: user.email,
        name: user.name || null,
        passwordHash: user.passwordHash || user.password_hash,
        providers: user.providers || [],
        emailVerified: user.emailVerified,
        verificationToken: user.verificationToken || null,
        verificationExpiresAt: user.verificationExpiresAt || null,
        plan: user.plan || 'hobby',
        billingStatus: user.billingStatus || 'active',
        billingEmail: user.billingEmail || user.email
      });
      
      console.log(`  ✓ Migrated user: ${user.email}`);
      success++;
    } catch (error) {
      console.error(`  ✗ Failed to migrate user ${user.email}:`, error.message);
      failed++;
    }
  }
  
  console.log(`  Completed: ${success} success, ${failed} failed`);
  return { success, failed };
}

async function migrateSessions() {
  console.log('\n📦 Migrating sessions...');
  
  const sessions = await loadJsonFile(SESSIONS_FILE, {});
  const sessionCount = Object.keys(sessions).length;
  console.log(`  Found ${sessionCount} sessions in JSON`);
  
  if (sessionCount === 0) {
    console.log('  No sessions to migrate');
    return { success: 0, failed: 0, expired: 0 };
  }
  
  const now = Date.now();
  let success = 0;
  let failed = 0;
  let expired = 0;
  
  const db = getDatabase();
  const sessionRepo = require('../src/repositories/sessionRepository');
  
  for (const [token, session] of Object.entries(sessions)) {
    try {
      // Skip expired sessions
      if (session.expiresAt && session.expiresAt <= now) {
        expired++;
        continue;
      }
      
      // Check if user exists
      const user = userRepo.getUserById(session.userId);
      if (!user) {
        console.log(`  Skipping session for non-existent user: ${session.userId}`);
        failed++;
        continue;
      }
      
      // Create session in database
      sessionRepo.createSession({
        id: session.id || require('crypto').randomUUID(),
        userId: session.userId,
        token: token,
        deviceFingerprint: session.deviceFingerprint || null,
        ipAddress: session.ipAddress || null,
        userAgent: session.userAgent || null,
        expiresAt: session.expiresAt,
        createdAt: session.createdAt || now,
        lastAccessedAt: session.lastAccessedAt || now
      });
      
      success++;
    } catch (error) {
      console.error(`  ✗ Failed to migrate session:`, error.message);
      failed++;
    }
  }
  
  console.log(`  Completed: ${success} success, ${failed} failed, ${expired} expired`);
  return { success, failed, expired };
}

async function migrateAffiliates() {
  console.log('\n📦 Migrating affiliates...');
  
  const affiliates = await loadJsonFile(AFFILIATES_FILE, []);
  console.log(`  Found ${affiliates.length} affiliates in JSON`);
  
  if (affiliates.length === 0) {
    console.log('  No affiliates to migrate');
    return { success: 0, failed: 0 };
  }
  
  let success = 0;
  let failed = 0;
  
  const db = getDatabase();
  
  for (const affiliate of affiliates) {
    try {
      // Check if user exists
      const user = userRepo.getUserById(affiliate.userId);
      if (!user) {
        console.log(`  Skipping affiliate for non-existent user: ${affiliate.userId}`);
        failed++;
        continue;
      }
      
      // Insert affiliate
      const stmt = db.prepare(`
        INSERT INTO affiliates (
          id, user_id, codes, earnings, commission_rate,
          total_referrals, total_earnings_cents, created_at, updated_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
      `);
      
      stmt.run(
        affiliate.id || require('crypto').randomUUID(),
        affiliate.userId,
        JSON.stringify(affiliate.codes || []),
        JSON.stringify(affiliate.earnings || []),
        affiliate.commissionRate || 0.15,
        affiliate.totalReferrals || 0,
        affiliate.totalEarningsCents || 0,
        affiliate.createdAt || Date.now(),
        affiliate.updatedAt || Date.now()
      );
      
      console.log(`  ✓ Migrated affiliate for user: ${user.email}`);
      success++;
    } catch (error) {
      console.error(`  ✗ Failed to migrate affiliate:`, error.message);
      failed++;
    }
  }
  
  console.log(`  Completed: ${success} success, ${failed} failed`);
  return { success, failed };
}

async function createBackup() {
  console.log('\n💾 Creating backup of JSON files...');
  
  const backupDir = path.join(DATA_ROOT, `migration_backup_${Date.now()}`);
  
  if (!fs.existsSync(backupDir)) {
    fs.mkdirSync(backupDir, { recursive: true });
  }
  
  const files = [USERS_FILE, SESSIONS_FILE, AFFILIATES_FILE];
  let backedUp = 0;
  
  for (const file of files) {
    if (fs.existsSync(file)) {
      const fileName = path.basename(file);
      const backupPath = path.join(backupDir, fileName);
      fs.copyFileSync(file, backupPath);
      console.log(`  ✓ Backed up: ${fileName}`);
      backedUp++;
    }
  }
  
  console.log(`  Created backup in: ${backupDir}`);
  console.log(`  Backed up ${backedUp} files`);
  
  return backupDir;
}

async function runMigration() {
  console.log('🔄 Starting database migration...');
  console.log('  Source: JSON files in', DATA_ROOT);
  console.log('  Target: Database at', DATABASE_PATH);
  
  // Check if database exists
  if (!fs.existsSync(DATABASE_PATH)) {
    console.error('❌ Database not found. Please run setup-database.js first.');
    process.exit(1);
  }
  
  // Initialize encryption
  if (!DATABASE_ENCRYPTION_KEY) {
    console.error('❌ DATABASE_ENCRYPTION_KEY not set');
    process.exit(1);
  }
  
  try {
    initEncryption(DATABASE_ENCRYPTION_KEY);
    console.log('✅ Encryption initialized');
  } catch (error) {
    console.error('❌ Failed to initialize encryption:', error.message);
    process.exit(1);
  }
  
  // Initialize database
  try {
    initDatabase(DATABASE_PATH, { verbose: false });
    console.log('✅ Database connected');
  } catch (error) {
    console.error('❌ Failed to connect to database:', error.message);
    process.exit(1);
  }
  
  // Create backup
  const backupDir = await createBackup();
  
  // Run migrations
  const results = {
    users: await migrateUsers(),
    sessions: await migrateSessions(),
    affiliates: await migrateAffiliates()
  };
  
  // Close database
  closeDatabase();
  
  // Print summary
  console.log('\n📊 Migration Summary:');
  console.log('  Users:');
  console.log(`    ✓ Success: ${results.users.success}`);
  console.log(`    ✗ Failed: ${results.users.failed}`);
  console.log('  Sessions:');
  console.log(`    ✓ Success: ${results.sessions.success}`);
  console.log(`    ✗ Failed: ${results.sessions.failed}`);
  console.log(`    ⏰ Expired: ${results.sessions.expired}`);
  console.log('  Affiliates:');
  console.log(`    ✓ Success: ${results.affiliates.success}`);
  console.log(`    ✗ Failed: ${results.affiliates.failed}`);
  
  const totalSuccess = results.users.success + results.sessions.success + results.affiliates.success;
  const totalFailed = results.users.failed + results.sessions.failed + results.affiliates.failed;
  
  console.log('\n  Total:');
  console.log(`    ✓ Success: ${totalSuccess}`);
  console.log(`    ✗ Failed: ${totalFailed}`);
  
  console.log('\n✅ Migration complete!');
  console.log(`  Backup created in: ${backupDir}`);
  console.log('\nNext steps:');
  console.log('  1. Verify migration: node scripts/verify-migration.js');
  console.log('  2. Test the application with: USE_JSON_DATABASE=1 npm start');
  console.log('  3. Switch to database mode: unset USE_JSON_DATABASE && npm start');
}

// Run migration
runMigration().catch(error => {
  console.error('❌ Migration failed:', error);
  closeDatabase();
  process.exit(1);
});
