/**
 * @ai-summary Admin feature business logic
 * @ai-context Handles admin user management with audit logging
 */

import { AdminRepository } from '../data/admin.repository';
import { AdminUser, AdminAuditLog } from './admin.types';
import { logger } from '../../../core/logging/logger';
import { auditLogService } from '../../audit-log';

export class AdminService {
  constructor(private repository: AdminRepository) {}

  async getAdminByAuth0Sub(auth0Sub: string): Promise<AdminUser | null> {
    try {
      return await this.repository.getAdminByAuth0Sub(auth0Sub);
    } catch (error) {
      logger.error('Error getting admin by auth0_sub', { error });
      throw error;
    }
  }

  async getAdminByEmail(email: string): Promise<AdminUser | null> {
    try {
      return await this.repository.getAdminByEmail(email);
    } catch (error) {
      logger.error('Error getting admin by email', { error });
      throw error;
    }
  }

  async getAllAdmins(): Promise<AdminUser[]> {
    try {
      return await this.repository.getAllAdmins();
    } catch (error) {
      logger.error('Error getting all admins', { error });
      throw error;
    }
  }

  async getActiveAdmins(): Promise<AdminUser[]> {
    try {
      return await this.repository.getActiveAdmins();
    } catch (error) {
      logger.error('Error getting active admins', { error });
      throw error;
    }
  }

  async createAdmin(email: string, role: string, auth0Sub: string, createdBy: string): Promise<AdminUser> {
    try {
      // Check if admin already exists
      const normalizedEmail = email.trim().toLowerCase();
      const existing = await this.repository.getAdminByEmail(normalizedEmail);
      if (existing) {
        throw new Error(`Admin user with email ${normalizedEmail} already exists`);
      }

      // Create new admin
      const admin = await this.repository.createAdmin(auth0Sub, normalizedEmail, role, createdBy);

      // Log audit action (legacy)
      await this.repository.logAuditAction(createdBy, 'CREATE', admin.auth0Sub, 'admin_user', admin.email, {
        email,
        role
      });

      // Log to unified audit log
      await auditLogService.info(
        'admin',
        createdBy,
        `Admin user created: ${admin.email}`,
        'admin_user',
        admin.auth0Sub,
        { email: admin.email, role }
      ).catch(err => logger.error('Failed to log admin create audit event', { error: err }));

      logger.info('Admin user created', { email, role });
      return admin;
    } catch (error) {
      logger.error('Error creating admin', { error, email });
      throw error;
    }
  }

  async revokeAdmin(auth0Sub: string, revokedBy: string): Promise<AdminUser> {
    try {
      // Check that at least one active admin will remain
      const activeAdmins = await this.repository.getActiveAdmins();
      if (activeAdmins.length <= 1) {
        throw new Error('Cannot revoke the last active admin');
      }

      // Revoke the admin
      const admin = await this.repository.revokeAdmin(auth0Sub);

      // Log audit action (legacy)
      await this.repository.logAuditAction(revokedBy, 'REVOKE', auth0Sub, 'admin_user', admin.email);

      // Log to unified audit log
      await auditLogService.info(
        'admin',
        revokedBy,
        `Admin user revoked: ${admin.email}`,
        'admin_user',
        auth0Sub,
        { email: admin.email }
      ).catch(err => logger.error('Failed to log admin revoke audit event', { error: err }));

      logger.info('Admin user revoked', { auth0Sub, email: admin.email });
      return admin;
    } catch (error) {
      logger.error('Error revoking admin', { error, auth0Sub });
      throw error;
    }
  }

  async reinstateAdmin(auth0Sub: string, reinstatedBy: string): Promise<AdminUser> {
    try {
      // Reinstate the admin
      const admin = await this.repository.reinstateAdmin(auth0Sub);

      // Log audit action (legacy)
      await this.repository.logAuditAction(reinstatedBy, 'REINSTATE', auth0Sub, 'admin_user', admin.email);

      // Log to unified audit log
      await auditLogService.info(
        'admin',
        reinstatedBy,
        `Admin user reinstated: ${admin.email}`,
        'admin_user',
        auth0Sub,
        { email: admin.email }
      ).catch(err => logger.error('Failed to log admin reinstate audit event', { error: err }));

      logger.info('Admin user reinstated', { auth0Sub, email: admin.email });
      return admin;
    } catch (error) {
      logger.error('Error reinstating admin', { error, auth0Sub });
      throw error;
    }
  }

  async getAuditLogs(limit: number = 100, offset: number = 0): Promise<{ logs: AdminAuditLog[]; total: number }> {
    try {
      return await this.repository.getAuditLogs(limit, offset);
    } catch (error) {
      logger.error('Error fetching audit logs', { error });
      throw error;
    }
  }

  async linkAdminAuth0Sub(email: string, auth0Sub: string): Promise<AdminUser> {
    try {
      return await this.repository.updateAuth0SubByEmail(email.trim().toLowerCase(), auth0Sub);
    } catch (error) {
      logger.error('Error linking admin auth0_sub to email', { error, email, auth0Sub });
      throw error;
    }
  }
}
