/**
 * GoodGo Platform - Seed User Generation Script
 * 
 * Creates seed users with full login capability (passwords + PII hashing)
 * 
 * Usage:
 *   export FIELD_ENCRYPTION_KEY='hex-encoded-32-byte-key'
 *   npx tsx scripts/seed-with-auth.ts
 */

import crypto from 'node:crypto';
import { PrismaClient, UserRole, type KYCStatus } from '@prisma/client';
import * as bcrypt from 'bcrypt';

const prisma = new PrismaClient();

// ============================================================================
// Configuration
// ============================================================================

interface SeedUserConfig {
  id: string;
  phone: string;
  email: string;
  fullName: string;
  password: string;
  role: UserRole;
  kycStatus: KYCStatus;
  isActive: boolean;
}

const SEED_USERS: SeedUserConfig[] = [
  {
    id: 'seed-admin-001',
    phone: '0900000001',
    email: 'admin@goodgo.vn',
    fullName: 'Admin GoodGo',
    password: 'AdminPassword123',
    role: UserRole.ADMIN,
    kycStatus: 'VERIFIED',
    isActive: true,
  },
  {
    id: 'seed-agent-001',
    phone: '0900000002',
    email: 'agent.nguyen@goodgo.vn',
    fullName: 'Nguyễn Văn An',
    password: 'AgentPassword123',
    role: UserRole.AGENT,
    kycStatus: 'VERIFIED',
    isActive: true,
  },
  {
    id: 'seed-seller-001',
    phone: '0900000005',
    email: 'seller.pham@gmail.com',
    fullName: 'Phạm Đức Dũng',
    password: 'SellerPassword123',
    role: UserRole.SELLER,
    kycStatus: 'VERIFIED',
    isActive: true,
  },
  {
    id: 'seed-buyer-001',
    phone: '0900000004',
    email: 'buyer.le@gmail.com',
    fullName: 'Lê Minh Cường',
    password: 'BuyerPassword123',
    role: UserRole.BUYER,
    kycStatus: 'NONE',
    isActive: true,
  },
];

// ============================================================================
// Helper Functions
// ============================================================================

/**
 * Normalize Vietnamese phone number to +84... format
 */
function normalizeVietnamPhone(phone: string): string {
  const cleaned = phone.replace(/[\s.-]/g, '');
  if (cleaned.startsWith('+84')) return cleaned;
  if (cleaned.startsWith('84')) return `+${cleaned}`;
  if (cleaned.startsWith('0')) return `+84${cleaned.slice(1)}`;
  throw new Error(`Invalid phone format: ${phone}`);
}

/**
 * Derive HMAC key from encryption key (same as field-encryption.ts)
 */
function deriveHmacKey(encryptionKeyHex: string): Buffer {
  return crypto.hkdfSync(
    'sha256',
    Buffer.from(encryptionKeyHex, 'hex'),
    Buffer.alloc(0),
    Buffer.from('goodgo-field-hash', 'utf8'),
    32,
  ) as unknown as Buffer;
}

/**
 * Compute HMAC-SHA256 hash for searchable fields
 */
function computeHash(value: string, hmacKey: Buffer): string {
  const normalized = value.toLowerCase().trim();
  return crypto.createHmac('sha256', hmacKey).update(normalized).digest('hex');
}

/**
 * Hash password with bcrypt
 */
async function hashPassword(password: string): Promise<string> {
  if (password.length < 8) {
    throw new Error('Password must be at least 8 characters');
  }
  return bcrypt.hash(password, 12);
}

// ============================================================================
// Main Seeding Function
// ============================================================================

async function seedUsersWithAuth() {
  const encryptionKey = process.env['FIELD_ENCRYPTION_KEY'];
  if (!encryptionKey) {
    throw new Error('FIELD_ENCRYPTION_KEY environment variable is required');
  }

  const hmacKey = deriveHmacKey(encryptionKey);
  const stats = {
    created: 0,
    skipped: 0,
    errors: 0,
  };

  console.log('🌱 Seeding users with authentication...\n');

  for (const userConfig of SEED_USERS) {
    try {
      // Check if user already exists
      const existing = await prisma.user.findUnique({
        where: { id: userConfig.id },
      });

      if (existing) {
        console.log(`⏭️  Skipping ${userConfig.fullName} (already exists)`);
        stats.skipped++;
        continue;
      }

      // 1. Normalize phone
      const normalizedPhone = normalizeVietnamPhone(userConfig.phone);

      // 2. Compute hashes
      const phoneHash = computeHash(normalizedPhone, hmacKey);
      const emailHash = computeHash(userConfig.email, hmacKey);

      // 3. Hash password
      const passwordHash = await hashPassword(userConfig.password);

      // 4. Create user
      const user = await prisma.user.create({
        data: {
          id: userConfig.id,
          phone: normalizedPhone,
          phoneHash,
          email: userConfig.email,
          emailHash,
          passwordHash,
          fullName: userConfig.fullName,
          role: userConfig.role,
          kycStatus: userConfig.kycStatus,
          isActive: userConfig.isActive,
          totpEnabled: false,
          totpBackupCodes: [],
        },
      });

      console.log(`✅ Created ${user.fullName} (${user.role})`);
      console.log(`   📞 Phone: ${normalizedPhone}`);
      console.log(`   📧 Email: ${user.email}`);
      console.log(`   🔑 Can login with password: ${userConfig.password}\n`);

      stats.created++;
    } catch (error) {
      console.error(
        `❌ Error creating ${userConfig.fullName}:`,
        error instanceof Error ? error.message : error,
      );
      stats.errors++;
    }
  }

  // Summary
  console.log('📊 Seed Summary');
  console.log(`   Created: ${stats.created}`);
  console.log(`   Skipped: ${stats.skipped}`);
  console.log(`   Errors: ${stats.errors}`);

  if (stats.errors === 0 && stats.created > 0) {
    console.log('\n✅ Seed completed successfully!');
  }
}

// ============================================================================
// Test Login Function (optional)
// ============================================================================

/**
 * Verify that a created user can actually log in
 */
async function testLogin(userId: string, password: string): Promise<boolean> {
  const user = await prisma.user.findUnique({
    where: { id: userId },
  });

  if (!user || !user.passwordHash) {
    console.error('User not found or has no password');
    return false;
  }

  const isValid = await bcrypt.compare(password, user.passwordHash);
  return isValid;
}

// ============================================================================
// CLI Entry Point
// ============================================================================

async function main() {
  try {
    await seedUsersWithAuth();

    // Optionally test login
    const adminUser = SEED_USERS.find((u) => u.role === UserRole.ADMIN);
    if (adminUser) {
      console.log('\n🔐 Testing login...');
      const loginWorks = await testLogin(adminUser.id, adminUser.password);
      if (loginWorks) {
        console.log(`✅ Login test passed for ${adminUser.fullName}`);
      } else {
        console.error(`❌ Login test failed for ${adminUser.fullName}`);
      }
    }
  } catch (error) {
    console.error('Fatal error:', error);
    process.exit(1);
  } finally {
    await prisma.$disconnect();
  }
}

if (require.main === module) {
  main();
}

export { seedUsersWithAuth, testLogin };
