import { PrismaClient } from '@prisma/client';

import {
  generateUsernameFromEmail,
  hashPassword,
  validateUsername,
} from '@hexahost/auth';

const PLATFORM_ROLES = [
  'USER',
  'SUPPORT',
  'MODERATOR',
  'ADMIN',
  'SUPER_ADMIN',
] as const;

interface CliArgs {
  email: string;
  password: string;
  username?: string;
  displayName?: string;
}

function parseArgs(argv: string[]): CliArgs {
  const args: Record<string, string> = {};

  for (let i = 0; i < argv.length; i += 1) {
    const key = argv[i];
    const value = argv[i + 1];
    if (key?.startsWith('--') && value) {
      args[key.slice(2)] = value;
      i += 1;
    }
  }

  if (!args['email'] || !args['password']) {
    console.error(
      'Usage: bootstrap-admin --email <email> --password <password> [--username <name>] [--display-name <name>]',
    );
    process.exit(1);
  }

  if (args['password'].length < 12) {
    console.error('Password must be at least 12 characters.');
    process.exit(1);
  }

  return {
    email: args['email'].trim().toLowerCase(),
    password: args['password'],
    username: args['username'],
    displayName: args['display-name'],
  };
}

async function ensurePlatformRoles(prisma: PrismaClient): Promise<void> {
  for (const name of PLATFORM_ROLES) {
    await prisma.platformRole.upsert({
      where: { name },
      create: { name, description: `${name} platform role` },
      update: {},
    });
  }
}

async function main(): Promise<void> {
  const input = parseArgs(process.argv.slice(2));
  const prisma = new PrismaClient();

  try {
    await ensurePlatformRoles(prisma);

    const existing = await prisma.user.findUnique({
      where: { email: input.email },
    });

    if (existing) {
      const superAdminRole = await prisma.platformRole.findUnique({
        where: { name: 'SUPER_ADMIN' },
      });

      if (!superAdminRole) {
        throw new Error('SUPER_ADMIN role missing after seed');
      }

      await prisma.userPlatformRole.upsert({
        where: {
          userId_roleId: {
            userId: existing.id,
            roleId: superAdminRole.id,
          },
        },
        create: {
          userId: existing.id,
          roleId: superAdminRole.id,
        },
        update: {},
      });

      console.log(`User ${input.email} already exists — SUPER_ADMIN role ensured.`);
      return;
    }

    let username = input.username?.trim().toLowerCase();
    if (username) {
      const validation = validateUsername(username);
      if (!validation.valid) {
        throw new Error(validation.error ?? 'Invalid username');
      }
    } else {
      username = generateUsernameFromEmail(input.email);
    }

    const passwordHash = await hashPassword(input.password);

    const superAdminRole = await prisma.platformRole.findUniqueOrThrow({
      where: { name: 'SUPER_ADMIN' },
    });

    const user = await prisma.$transaction(async (tx) => {
      const created = await tx.user.create({
        data: {
          email: input.email,
          username,
          displayName: input.displayName ?? 'Administrator',
          emailVerifiedAt: new Date(),
          credentials: {
            create: { passwordHash },
          },
          platformRoles: {
            create: { roleId: superAdminRole.id },
          },
        },
      });

      await tx.auditEvent.create({
        data: {
          userId: created.id,
          action: 'admin.bootstrap',
          entityType: 'user',
          entityId: created.id,
          metadata: { source: 'bootstrap-cli' },
        },
      });

      return created;
    });

    console.log(`Admin user created: ${user.email} (${user.id})`);
  } finally {
    await prisma.$disconnect();
  }
}

void main().catch((error: unknown) => {
  console.error(error instanceof Error ? error.message : error);
  process.exit(1);
});
