import mongoose from 'mongoose';
import bcrypt from 'bcryptjs';
import UserModel from '../models/User';
import AdminModel from '../models/Admin';
import 'dotenv/config';

interface AdminUserData {
  first_name: string;
  last_name: string;
  email: string;
  password: string;
  role: 'ADMIN';
  isProfileComplete: boolean;
}

interface AdminData {
  full_name: string;
  email: string;
  password: string;
  two_factor_enabled: boolean;
}

class AdminSeeder {
  private static async connectToDatabase(): Promise<void> {
    try {
      if (mongoose.connection.readyState === 0) {
        await mongoose.connect(process.env.DATABASE_URL!);
        console.log('✅ Connected to MongoDB');
      }
    } catch (error) {
      console.error('❌ Database connection failed:', error);
      throw error;
    }
  }

  private static async hashPassword(password: string): Promise<string> {
    const saltRounds = 12;
    return await bcrypt.hash(password, saltRounds);
  }

  /**
   * Seed admin user in the User collection with ADMIN role
   */
  public static async seedAdminUser(): Promise<void> {
    try {
      await this.connectToDatabase();

      const adminEmail = process.env.ADMIN_EMAIL || 'admin@quickconnect.com';
      const adminPassword = process.env.ADMIN_PASSWORD || 'Admin@123456';

      // Check if admin user already exists
      const existingAdminUser = await UserModel.findOne({
        email: adminEmail,
        role: 'ADMIN',
      });

      if (existingAdminUser) {
        console.log('⚠️  Admin user already exists in User collection');
        return;
      }

      const hashedPassword = await this.hashPassword(adminPassword);

      const adminUserData: AdminUserData = {
        first_name: 'System',
        last_name: 'Administrator',
        email: adminEmail,
        password: hashedPassword,
        role: 'ADMIN',
        isProfileComplete: true,
      };

      const adminUser = new UserModel(adminUserData);
      await adminUser.save();

      console.log('✅ Admin user created successfully in User collection');
      console.log(`📧 Email: ${adminEmail}`);
      console.log(`🔑 Password: ${adminPassword}`);
      console.log('⚠️  Please change the default password after first login');
    } catch (error) {
      console.error('❌ Error seeding admin user:', error);
      throw error;
    }
  }

  /**
   * Seed admin in the Admin collection
   */
  public static async seedAdmin(): Promise<void> {
    try {
      await this.connectToDatabase();

      const adminEmail = process.env.ADMIN_EMAIL || 'admin@quickconnect.com';
      const adminPassword = process.env.ADMIN_PASSWORD || 'Admin@123456';

      // Check if admin already exists
      const existingAdmin = await AdminModel.findOne({ email: adminEmail });

      if (existingAdmin) {
        console.log('⚠️  Admin already exists in Admin collection');
        return;
      }

      const hashedPassword = await this.hashPassword(adminPassword);

      const adminData: AdminData = {
        full_name: 'System Administrator',
        email: adminEmail,
        password: hashedPassword,
        two_factor_enabled: false,
      };

      const admin = new AdminModel(adminData);
      await admin.save();

      console.log('✅ Admin created successfully in Admin collection');
      console.log(`📧 Email: ${adminEmail}`);
      console.log(`🔑 Password: ${adminPassword}`);
      console.log('⚠️  Please change the default password after first login');
    } catch (error) {
      console.error('❌ Error seeding admin:', error);
      throw error;
    }
  }

  /**
   * Seed both admin user and admin records
   */
  public static async seedAll(): Promise<void> {
    try {
      console.log('🌱 Starting admin seeding process...');

      await this.seedAdminUser();
      await this.seedAdmin();

      console.log('✅ Admin seeding completed successfully');
    } catch (error) {
      console.error('❌ Admin seeding failed:', error);
      throw error;
    } finally {
      await mongoose.connection.close();
      console.log('🔌 Database connection closed');
    }
  }

  /**
   * Remove all admin records (for testing/reset purposes)
   */
  public static async resetAdmins(): Promise<void> {
    try {
      await this.connectToDatabase();

      const adminEmail = process.env.ADMIN_EMAIL || 'admin@quickconnect.com';

      // Remove from User collection
      const deletedUser = await UserModel.deleteOne({
        email: adminEmail,
        role: 'ADMIN',
      });

      // Remove from Admin collection
      const deletedAdmin = await AdminModel.deleteOne({ email: adminEmail });

      console.log(
        `🗑️  Removed ${deletedUser.deletedCount} admin user(s) from User collection`
      );
      console.log(
        `🗑️  Removed ${deletedAdmin.deletedCount} admin(s) from Admin collection`
      );
    } catch (error) {
      console.error('❌ Error resetting admins:', error);
      throw error;
    } finally {
      await mongoose.connection.close();
      console.log('🔌 Database connection closed');
    }
  }
}

export default AdminSeeder;

// CLI execution support
if (require.main === module) {
  const command = process.argv[2];

  switch (command) {
    case 'seed':
      AdminSeeder.seedAll()
        .then(() => process.exit(0))
        .catch(() => process.exit(1));
      break;

    case 'seed-user':
      AdminSeeder.seedAdminUser()
        .then(() => process.exit(0))
        .catch(() => process.exit(1));
      break;

    case 'seed-admin':
      AdminSeeder.seedAdmin()
        .then(() => process.exit(0))
        .catch(() => process.exit(1));
      break;

    case 'reset':
      AdminSeeder.resetAdmins()
        .then(() => process.exit(0))
        .catch(() => process.exit(1));
      break;

    default:
      console.log('Usage:');
      console.log('  npm run seed:admin seed       - Seed both admin user and admin');
      console.log(
        '  npm run seed:admin seed-user  - Seed only admin user (User collection)'
      );
      console.log(
        '  npm run seed:admin seed-admin - Seed only admin (Admin collection)'
      );
      console.log('  npm run seed:admin reset      - Remove all admin records');
      process.exit(1);
  }
}
