import { Controller, Get, HttpException, HttpStatus, Param, Query, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger';
import { RequireModule } from 'src/auth/decorators/require-module.decorator';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { ModuleGuard } from 'src/auth/guards/module.guard';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import { PrismaService } from '../prisma/prisma.service';
import { AuditService } from './audit.service';

@ApiTags('Auditoría')
@Controller({ path: 'audit', version: '1' })
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('ADMINISTRACION')
export class AuditController {
  constructor(
    private readonly auditService: AuditService,
    private readonly prisma: PrismaService,
  ) {}

  private async getEmpresaType(empresaId: string): Promise<string | null> {
    const empresa = await this.prisma.empresas.findUnique({
      where: { id: empresaId },
      select: { type: true },
    });
    return empresa?.type ?? null;
  }

  @Get('health')
  @ApiOperation({ summary: 'Verificar el estado del servicio de auditoría' })
  healthCheck() {
    return { status: 'ok', message: 'Audit controller is working' };
  }

  /**
   * Obtener logs de auditoría paginados para la empresa del usuario.
   * Soporta filtros por acción, tipo de entidad, búsqueda y rango de fechas.
   */
  @Get('logs')
  @RequirePermission('ADMINISTRACION', 'ADM_AUD_AUDITORIA_VER')
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Obtener logs de auditoría paginados' })
  @ApiQuery({
    name: 'action',
    required: false,
    description: 'Filtrar por acción (CREATE, UPDATE, DELETE, APPROVE, etc.)',
  })
  @ApiQuery({
    name: 'entity_type',
    required: false,
    description: 'Filtrar por tipo de entidad (suscripcion, comprobante_pago, etc.)',
  })
  @ApiQuery({ name: 'user_id', required: false, description: 'Filtrar por ID de usuario que ejecutó la acción' })
  @ApiQuery({ name: 'search', required: false, description: 'Buscar en la descripción del log' })
  @ApiQuery({ name: 'fecha_desde', required: false, description: 'Fecha desde (YYYY-MM-DD)' })
  @ApiQuery({ name: 'fecha_hasta', required: false, description: 'Fecha hasta (YYYY-MM-DD)' })
  @ApiQuery({
    name: 'empresa_filtro_id',
    required: false,
    description: 'Filtrar por empresa específica (solo holding/reseller)',
  })
  @ApiQuery({ name: 'caja_id', required: false, description: 'Filtrar por ID de caja' })
  @ApiQuery({ name: 'sesion_caja_id', required: false, description: 'Filtrar por ID de sesión de caja' })
  @ApiQuery({ name: 'terminal_id', required: false, description: 'Filtrar por ID de terminal/dispositivo' })
  @ApiQuery({ name: 'page', required: false, description: 'Número de página (default: 1)' })
  @ApiQuery({ name: 'limit', required: false, description: 'Registros por página (default: 25, max: 100)' })
  @ApiResponse({ status: 200, description: 'Lista paginada de logs de auditoría' })
  async getLogs(
    @GetUser() user: LoginUserInfo,
    @Query('action') action?: string,
    @Query('entity_type') entityType?: string,
    @Query('user_id') userId?: string,
    @Query('search') search?: string,
    @Query('fecha_desde') fechaDesde?: string,
    @Query('fecha_hasta') fechaHasta?: string,
    @Query('empresa_filtro_id') empresaFiltroId?: string,
    @Query('caja_id') cajaId?: string,
    @Query('sesion_caja_id') sesionCajaId?: string,
    @Query('terminal_id') terminalId?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    try {
      const empresaId = user.empresa_id;
      if (!empresaId) {
        throw new HttpException('No se pudo determinar la empresa del usuario', HttpStatus.BAD_REQUEST);
      }

      const empresaType = await this.getEmpresaType(empresaId);

      return this.auditService.getPaginated(empresaId, empresaType, {
        action: action || undefined,
        entity_type: entityType || undefined,
        user_id: userId || undefined,
        search: search || undefined,
        fecha_desde: fechaDesde || undefined,
        fecha_hasta: fechaHasta || undefined,
        empresa_filtro_id: empresaFiltroId || undefined,
        caja_id: cajaId || undefined,
        sesion_caja_id: sesionCajaId || undefined,
        terminal_id: terminalId || undefined,
        page: page ? parseInt(page, 10) : undefined,
        limit: limit ? parseInt(limit, 10) : undefined,
      });
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException('Error al obtener logs de auditoría', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * Obtener opciones de filtro (actions y entity_types disponibles).
   */
  @Get('filter-options')
  @RequirePermission('ADMINISTRACION', 'ADM_AUD_AUDITORIA_VER')
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Obtener opciones de filtro para auditoría' })
  @ApiResponse({ status: 200, description: 'Opciones de filtro disponibles' })
  async getFilterOptions(@GetUser() user: LoginUserInfo) {
    try {
      const empresaId = user.empresa_id;
      if (!empresaId) {
        throw new HttpException('No se pudo determinar la empresa del usuario', HttpStatus.BAD_REQUEST);
      }

      const empresaType = await this.getEmpresaType(empresaId);
      return this.auditService.getFilterOptions(empresaId, empresaType);
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException('Error al obtener opciones de filtro', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * Obtener historial de auditoría de una entidad específica.
   */
  @Get('entity/:entityType/:entityId')
  @RequirePermission('ADMINISTRACION', 'ADM_AUD_AUDITORIA_VER')
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Obtener historial de una entidad específica' })
  @ApiParam({ name: 'entityType', description: 'Tipo de entidad (ej: suscripcion, comprobante_pago)' })
  @ApiParam({ name: 'entityId', description: 'ID de la entidad' })
  @ApiQuery({ name: 'limit', required: false, description: 'Cantidad máxima de registros (default: 50)' })
  @ApiResponse({ status: 200, description: 'Historial de auditoría de la entidad' })
  async getEntityHistory(
    @GetUser() user: LoginUserInfo,
    @Param('entityType') entityType: string,
    @Param('entityId') entityId: string,
    @Query('limit') limit?: string,
  ) {
    try {
      return this.auditService.getByEntity(entityType, entityId, limit ? parseInt(limit, 10) : undefined);
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException('Error al obtener historial de entidad', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}
