import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcryptjs';
import { logger } from '@goodgo/logger';

const prisma = new PrismaClient();

/**
 * EN: Seed database with initial data
 * VI: Seed database với dữ liệu ban đầu
 */
async function main() {
  logger.info('Starting database seed / Bắt đầu seed database');

  // EN: Create default roles
  // VI: Tạo roles mặc định
  const adminRole = await prisma.role.upsert({
    where: { name: 'ADMIN' },
    update: {},
    create: {
      name: 'ADMIN',
      displayName: 'Administrator',
      description: 'Full system access',
      isSystem: true,
    },
  });

  const userRole = await prisma.role.upsert({
    where: { name: 'USER' },
    update: {},
    create: {
      name: 'USER',
      displayName: 'User',
      description: 'Standard user access',
      isSystem: true,
    },
  });

  const moderatorRole = await prisma.role.upsert({
    where: { name: 'MODERATOR' },
    update: {},
    create: {
      name: 'MODERATOR',
      displayName: 'Moderator',
      description: 'Moderation access',
      isSystem: true,
    },
  });

  logger.info('Roles created / Roles đã được tạo', { adminRole, userRole, moderatorRole });

  // EN: Create default permissions
  // VI: Tạo permissions mặc định
  const permissions = [
    // User permissions
    { resource: 'users', action: 'create', scope: null },
    { resource: 'users', action: 'read', scope: 'own' },
    { resource: 'users', action: 'read', scope: 'all' },
    { resource: 'users', action: 'update', scope: 'own' },
    { resource: 'users', action: 'update', scope: 'all' },
    { resource: 'users', action: 'delete', scope: 'all' },
    
    // RBAC permissions
    { resource: 'rbac', action: 'assign', scope: null },
    { resource: 'rbac', action: 'revoke', scope: null },
    { resource: 'rbac', action: 'grant', scope: null },
    { resource: 'rbac', action: 'read', scope: null },
    
    // Auth permissions
    { resource: 'auth', action: 'manage', scope: null },
  ];

  const createdPermissions = [];
  for (const perm of permissions) {
    // EN: Handle nullable scope in upsert
    // VI: Xử lý scope nullable trong upsert
    let permission;
    if (perm.scope !== null) {
      // Use compound unique constraint when scope is not null
      permission = await prisma.permission.upsert({
        where: {
          resource_action_scope: {
            resource: perm.resource,
            action: perm.action,
            scope: perm.scope,
          },
        },
        update: {},
        create: {
          resource: perm.resource,
          action: perm.action,
          scope: perm.scope,
          description: `${perm.action} ${perm.resource}${perm.scope ? ` (${perm.scope})` : ''}`,
        },
      });
    } else {
      // Use find/create when scope is null to avoid unique constraint issues
      permission = await prisma.permission.findFirst({
        where: {
          resource: perm.resource,
          action: perm.action,
          scope: null,
        },
      });

      if (!permission) {
        permission = await prisma.permission.create({
          data: {
            resource: perm.resource,
            action: perm.action,
            scope: perm.scope,
            description: `${perm.action} ${perm.resource}${perm.scope ? ` (${perm.scope})` : ''}`,
          },
        });
      }
    }
    createdPermissions.push(permission);
  }

  logger.info('Permissions created / Permissions đã được tạo', { count: createdPermissions.length });

  // EN: Assign permissions to roles
  // VI: Gán permissions cho roles
  // Admin gets all permissions
  for (const permission of createdPermissions) {
    await prisma.rolePermission.upsert({
      where: {
        roleId_permissionId: {
          roleId: adminRole.id,
          permissionId: permission.id,
        },
      },
      update: {},
      create: {
        roleId: adminRole.id,
        permissionId: permission.id,
      },
    });
  }

  // User gets basic permissions
  const userPermissions = createdPermissions.filter(p => 
    (p.resource === 'users' && p.action === 'read' && p.scope === 'own') ||
    (p.resource === 'users' && p.action === 'update' && p.scope === 'own')
  );

  for (const permission of userPermissions) {
    await prisma.rolePermission.upsert({
      where: {
        roleId_permissionId: {
          roleId: userRole.id,
          permissionId: permission.id,
        },
      },
      update: {},
      create: {
        roleId: userRole.id,
        permissionId: permission.id,
      },
    });
  }

  // EN: Create admin user
  // VI: Tạo user admin
  const adminPassword = await bcrypt.hash('admin123', 12);
  const adminUser = await prisma.user.upsert({
    where: { email: 'admin@goodgo.com' },
    update: {},
    create: {
      email: 'admin@goodgo.com',
      username: 'admin',
      passwordHash: adminPassword,
      isActive: true,
      emailVerified: true,
    },
  });

  // Assign admin role
  await prisma.userRole.upsert({
    where: {
      userId_roleId: {
        userId: adminUser.id,
        roleId: adminRole.id,
      },
    },
    update: {},
    create: {
      userId: adminUser.id,
      roleId: adminRole.id,
    },
  });

  logger.info('Admin user created / User admin đã được tạo', {
    email: adminUser.email,
    password: 'admin123', // Only for development!
  });

  // EN: Create test user
  // VI: Tạo user test
  const testPassword = await bcrypt.hash('test123', 12);
  const testUser = await prisma.user.upsert({
    where: { email: 'test@goodgo.com' },
    update: {},
    create: {
      email: 'test@goodgo.com',
      username: 'testuser',
      passwordHash: testPassword,
      isActive: true,
      emailVerified: true,
    },
  });

  // Assign user role
  await prisma.userRole.upsert({
    where: {
      userId_roleId: {
        userId: testUser.id,
        roleId: userRole.id,
      },
    },
    update: {},
    create: {
      userId: testUser.id,
      roleId: userRole.id,
    },
  });

  logger.info('Test user created / User test đã được tạo', {
    email: testUser.email,
    password: 'test123', // Only for development!
  });

  // EN: Create sample organization (optional - for IAM features)
  // VI: Tạo tổ chức mẫu (tùy chọn - cho tính năng IAM)
  const sampleOrg = await prisma.organization.upsert({
    where: { domain: 'goodgo.com' },
    update: {},
    create: {
      name: 'GoodGo',
      domain: 'goodgo.com',
      isActive: true,
      settings: {},
    },
  }).catch(() => null); // Ignore if already exists or schema not migrated yet

  if (sampleOrg) {
    logger.info('Sample organization created / Tổ chức mẫu đã được tạo', { organizationId: sampleOrg.id });
  }

  logger.info('Database seed completed / Seed database đã hoàn thành');
}

main()
  .catch((error) => {
    logger.error('Seed failed / Seed thất bại', { error: error.message, stack: error.stack });
    console.error('Full error:', error);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
