import { DataSource } from 'typeorm';
import { randomBytes } from 'crypto';
import { Role } from '../src/roles/role.entity';
import { Permission } from '../src/permissions/permission.entity';
import { User } from '../src/users/user.entity';
import { AppSetting } from '../src/app-settings/app-setting.entity';
import * as bcrypt from 'bcrypt';

const ROLES = [
  { name: 'SUPER_ADMIN', description: 'Full system access' },
  { name: 'CONTENT_ADMIN', description: 'Content creation and publishing' },
  { name: 'MEDICAL_EDITOR', description: 'Medical content editing' },
  { name: 'CONTENT_REVIEWER', description: 'Content review and approval' },
  { name: 'MEDIA_MANAGER', description: 'Media management' },
  { name: 'REPORT_VIEWER', description: 'View analytics and reports' },
];

const PERMISSIONS = [
  // Dashboard
  { name: 'dashboard.view', description: 'View dashboard' },

  // Section permissions
  { name: 'section.view', description: 'View sections' },
  { name: 'section.create', description: 'Create sections' },
  { name: 'section.update', description: 'Update sections' },
  { name: 'section.delete', description: 'Delete sections' },
  { name: 'section.publish', description: 'Publish sections' },

  // Module permissions
  { name: 'module.view', description: 'View modules' },
  { name: 'module.create', description: 'Create modules' },
  { name: 'module.update', description: 'Update modules' },
  { name: 'module.delete', description: 'Delete modules' },
  { name: 'module.publish', description: 'Publish modules' },

  // Lesson permissions
  { name: 'lesson.view', description: 'View lessons' },
  { name: 'lesson.create', description: 'Create lessons' },
  { name: 'lesson.update', description: 'Update lessons' },
  { name: 'lesson.delete', description: 'Delete lessons' },
  { name: 'lesson.publish', description: 'Publish lessons' },

  // Activity permissions
  { name: 'activity.view', description: 'View activities' },
  { name: 'activity.create', description: 'Create activities' },
  { name: 'activity.update', description: 'Update activities' },
  { name: 'activity.delete', description: 'Delete activities' },
  { name: 'activity.publish', description: 'Publish activities' },

  // Media permissions
  { name: 'media.view', description: 'View media' },
  { name: 'media.upload', description: 'Upload media' },
  { name: 'media.update', description: 'Update media' },
  { name: 'media.delete', description: 'Delete media' },

  // Case permissions
  { name: 'case.view', description: 'View cases' },
  { name: 'case.create', description: 'Create cases' },
  { name: 'case.update', description: 'Update cases' },
  { name: 'case.delete', description: 'Delete cases' },
  { name: 'case.publish', description: 'Publish cases' },

  // Decision tree permissions
  { name: 'decision_tree.view', description: 'View decision trees' },
  { name: 'decision_tree.create', description: 'Create decision trees' },
  { name: 'decision_tree.update', description: 'Update decision trees' },
  { name: 'decision_tree.delete', description: 'Delete decision trees' },
  { name: 'decision_tree.publish', description: 'Publish decision trees' },

  // User permissions
  { name: 'user.view', description: 'View users' },
  { name: 'user.create', description: 'Create users' },
  { name: 'user.update', description: 'Update users' },
  { name: 'user.delete', description: 'Delete users' },

  // Role permissions
  { name: 'role.view', description: 'View roles' },
  { name: 'role.create', description: 'Create roles' },
  { name: 'role.update', description: 'Update roles' },
  { name: 'role.delete', description: 'Delete roles' },

  // Audit logs
  { name: 'audit.view', description: 'View audit logs' },

  // Analytics
  { name: 'analytics.view', description: 'View analytics' },

  // Settings
  { name: 'settings.view', description: 'View settings' },
  { name: 'settings.update', description: 'Update settings' },
];

// Role to Permissions mapping
const ROLE_PERMISSIONS: { [key: string]: string[] } = {
  SUPER_ADMIN: PERMISSIONS.map((p) => p.name),
  CONTENT_ADMIN: [
    'dashboard.view',
    'section.view',
    'section.create',
    'section.update',
    'section.delete',
    'section.publish',
    'module.view',
    'module.create',
    'module.update',
    'module.delete',
    'module.publish',
    'lesson.view',
    'lesson.create',
    'lesson.update',
    'lesson.delete',
    'lesson.publish',
    'activity.view',
    'activity.create',
    'activity.update',
    'activity.delete',
    'activity.publish',
    'media.view',
    'media.upload',
    'media.update',
    'media.delete',
    'case.view',
    'case.create',
    'case.update',
    'case.delete',
    'case.publish',
    'decision_tree.view',
    'decision_tree.create',
    'decision_tree.update',
    'decision_tree.delete',
    'decision_tree.publish',
    'user.view',
    'analytics.view',
  ],
  MEDICAL_EDITOR: [
    'dashboard.view',
    'section.view',
    'module.view',
    'lesson.view',
    'activity.view',
    'activity.update',
    'media.view',
    'case.view',
    'case.create',
    'case.update',
    'analytics.view',
  ],
  CONTENT_REVIEWER: [
    'dashboard.view',
    'section.view',
    'module.view',
    'lesson.view',
    'activity.view',
    'user.view',
    'audit.view',
    'analytics.view',
  ],
  MEDIA_MANAGER: [
    'dashboard.view',
    'media.view',
    'media.upload',
    'media.update',
    'media.delete',
  ],
  REPORT_VIEWER: [
    'dashboard.view',
    'analytics.view',
    'audit.view',
  ],
};

/**
 * Educational safety notice required by section 35. This is platform
 * messaging, not clinical content - the medical team owns everything else
 * through the admin panel.
 */
const DEFAULT_SETTINGS: { key: string; value: Record<string, any> }[] = [
  {
    key: 'app.disclaimer',
    value: {
      value:
        'This application is for education and training only. It does not ' +
        'provide medical advice and must not be used for clinical ' +
        'decision-making. Always follow your institution’s protocols and ' +
        'consult the primary literature.',
    },
  },
  { key: 'content.cache_ttl_minutes', value: { value: 60 } },
];

async function seed(dataSource: DataSource) {
  const roleRepo = dataSource.getRepository(Role);
  const permRepo = dataSource.getRepository(Permission);
  const userRepo = dataSource.getRepository(User);
  const settingRepo = dataSource.getRepository(AppSetting);

  console.log('🌱 Seeding database...');

  // Permissions -------------------------------------------------------------
  const createdPerms: Permission[] = [];
  for (const p of PERMISSIONS) {
    const existing = await permRepo.findOne({ where: { name: p.name } });
    createdPerms.push(existing ?? (await permRepo.save(permRepo.create(p))));
  }
  console.log(`✅ ${createdPerms.length} permissions available`);

  // Roles -------------------------------------------------------------------
  // Permission sets are re-synced on every run so newly added permissions
  // reach the roles that should have them.
  const createdRoles: Role[] = [];
  for (const r of ROLES) {
    const role =
      (await roleRepo.findOne({ where: { name: r.name }, relations: ['permissions'] })) ??
      roleRepo.create(r);

    role.description = r.description;
    role.permissions = createdPerms.filter((p) =>
      ROLE_PERMISSIONS[r.name].includes(p.name),
    );
    createdRoles.push(await roleRepo.save(role));
  }
  console.log(`✅ ${createdRoles.length} roles synced`);

  // Default settings --------------------------------------------------------
  for (const setting of DEFAULT_SETTINGS) {
    const existing = await settingRepo.findOne({ where: { key: setting.key } });
    if (!existing) await settingRepo.save(settingRepo.create(setting));
  }
  console.log(`✅ Default settings ensured`);

  // Bootstrap administrator -------------------------------------------------
  const adminEmail = process.env.SEED_ADMIN_EMAIL || 'admin@mteer.local';
  const existing = await userRepo.findOne({ where: { email: adminEmail } });

  if (existing) {
    console.log(`ℹ️  Admin user already exists: ${adminEmail}`);
  } else {
    // A generated password is safer than a well-known default; it is printed
    // once here and never stored in plain text.
    const generated = !process.env.SEED_ADMIN_PASSWORD;
    const password = process.env.SEED_ADMIN_PASSWORD || randomBytes(12).toString('base64url');

    const admin = userRepo.create({
      email: adminEmail,
      passwordHash: await bcrypt.hash(password, 12),
      displayName: 'Super Admin',
      isActive: true,
      roles: createdRoles.filter((r) => r.name === 'SUPER_ADMIN'),
    });
    await userRepo.save(admin);

    console.log(`✅ Created admin user: ${adminEmail}`);
    if (generated) {
      console.log(`   Temporary password: ${password}`);
      console.log('   Change it after first login (POST /api/v1/admin/auth/change-password).');
    }
  }

  console.log('✅ Database seeding completed!');
}

export default seed;
