import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as argon2 from 'argon2';
import { randomBytes } from 'crypto';
import { User } from '../../entities/user.entity';
import { License } from '../../entities/license.entity';

/**
 * Bootstraps the first admin account on a fresh database.
 *
 * A fresh deploy builds the schema via docker-entrypoint-initdb.d but contains
 * zero users, so the panel has no possible login. If ADMIN_EMAIL and
 * ADMIN_PASSWORD are set and the users table is empty, this creates a
 * super-admin user plus an active license — the same rows the register flow
 * would create. It never runs against a database that already has users.
 */
@Injectable()
export class AdminSeedService implements OnApplicationBootstrap {
  private readonly logger = new Logger(AdminSeedService.name);

  constructor(
    private readonly config: ConfigService,
    @InjectRepository(User) private readonly userRepository: Repository<User>,
    @InjectRepository(License) private readonly licenseRepository: Repository<License>,
  ) {}

  async onApplicationBootstrap(): Promise<void> {
    try {
      await this.seedAdminIfEmpty();
    } catch (err) {
      // A failed seed must not take the API down — surface it loudly and move on
      this.logger.error(`Admin bootstrap failed: ${(err as Error).message}`, (err as Error).stack);
    }
  }

  private async seedAdminIfEmpty(): Promise<void> {
    const email = this.config.get<string>('admin.email');
    const password = this.config.get<string>('admin.password');
    const username = this.config.get<string>('admin.username') || 'Commander';

    if (!email || !password) {
      this.logger.log('Admin bootstrap skipped: ADMIN_EMAIL / ADMIN_PASSWORD not set');
      return;
    }

    const userCount = await this.userRepository.count();
    if (userCount > 0) {
      return;
    }

    const password_hash = await argon2.hash(password);
    const user = this.userRepository.create({
      email: email.toLowerCase(),
      username,
      password_hash,
      email_verified: true,
      is_super_admin: true,
    });
    await this.userRepository.save(user);

    const licenseKey = this.config.get<string>('admin.licenseKey') || this.generateLicenseKey();
    const license = this.licenseRepository.create({
      license_key: licenseKey,
      owner_user_id: user.id,
      status: 'active',
      modules_enabled: [],
      webstore_active: false,
    });
    await this.licenseRepository.save(license);

    this.logger.log(`Bootstrap admin created: ${user.email} (license ${license.license_key})`);
  }

  private generateLicenseKey(): string {
    const part1 = randomBytes(2).toString('hex').toUpperCase();
    const part2 = randomBytes(2).toString('hex').toUpperCase();
    const part3 = randomBytes(2).toString('hex').toUpperCase();
    return `CORR-${part1}-${part2}-${part3}`;
  }
}
