import {
  Body,
  Controller,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import type { LoginUserInfo } from '../auth/dto/login.dto';
import { GetUser } from '../auth/get-user.decorator';
import { RequireModule, RequirePermission } from '../auth/decorators';
import { ModuleGuard } from '../auth/guards/module.guard';
import { PermissionGuard } from '../auth/guards/permission.guard';
import {
  AprobarRendicionDto,
  CreateRendicionDto,
  EnviarTesoreriaDto,
  ESTADOS_RENDICION,
  RechazarRendicionDto,
  RevisarRendicionDto,
  VerificarMedioPagoDto,
} from './dto/rendiciones.dto';
import { RendicionesService } from './rendiciones.service';

/**
 * RendicionesController
 * ────────────────────────────────────────────────────────────────────────
 * Flujo:
 *   POST   /rendiciones                                    crear (BORRADOR)
 *   POST   /rendiciones/:id/enviar-tesoreria               BORRADOR/OBSERVADO → PENDIENTE
 *   PATCH  /rendiciones/:id/medios-pago/:mpId/verificar    verificar medio (Tesorería)
 *   POST   /rendiciones/:id/aprobar                        PENDIENTE → APROBADO
 *   POST   /rendiciones/:id/rechazar                       PENDIENTE → OBSERVADO/RECHAZADO
 *   GET    /rendiciones                                    listar con filtros
 *   GET    /rendiciones/:id                                detalle
 *   GET    /rendiciones/resumen-diario                     KPIs
 *   GET    /rendiciones/recibos-disponibles                recibos sin rendir
 *   PATCH  /rendiciones/:id/revisar                        (legacy, deprecated)
 */
@ApiTags('Rendiciones de Cobranza')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('COBRANZAS')
@Controller('rendiciones')
export class RendicionesController {
  constructor(private readonly service: RendicionesService) {}

  @Get('resumen-diario')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_VER')
  @ApiOperation({ summary: 'Resumen diario de rendiciones (KPIs)' })
  @ApiQuery({ name: 'fecha', required: false, description: 'YYYY-MM-DD (default: hoy)' })
  getResumenDiario(@GetUser() user: LoginUserInfo, @Query('fecha') fecha?: string) {
    return this.service.getResumenDiario(user.empresa_id, fecha);
  }

  @Get('recibos-disponibles')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_CREAR')
  @ApiOperation({ summary: 'Recibos de cobro sin rendición asignada' })
  @ApiQuery({ name: 'cobrador_id', required: false })
  @ApiQuery({ name: 'fecha', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'moneda_id', required: false })
  getRecibosDisponibles(
    @GetUser() user: LoginUserInfo,
    @Query('cobrador_id') cobradorId?: string,
    @Query('fecha') fecha?: string,
    @Query('moneda_id') monedaId?: string,
  ) {
    return this.service.getRecibosDisponibles(user.empresa_id, cobradorId, fecha, monedaId);
  }

  @Get('reportes/cobranzas-dia')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_VER')
  @ApiOperation({ summary: 'Reporte: Cobranzas agrupadas por cobrador en un rango de fechas' })
  @ApiQuery({ name: 'fecha', required: false, description: 'YYYY-MM-DD (atajo: usa el mismo día como desde/hasta)' })
  @ApiQuery({ name: 'fecha_desde', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'fecha_hasta', required: false, description: 'YYYY-MM-DD' })
  reporteCobranzasDia(
    @GetUser() user: LoginUserInfo,
    @Query('fecha') fecha?: string,
    @Query('fecha_desde') fechaDesde?: string,
    @Query('fecha_hasta') fechaHasta?: string,
  ) {
    return this.service.reporteCobranzasDia(
      user.empresa_id,
      fechaDesde || fecha,
      fechaHasta || fecha,
    );
  }

  @Get('reportes/pendientes')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_VER')
  @ApiOperation({ summary: 'Reporte: Rendiciones pendientes de verificación con antigüedad' })
  reportePendientes(@GetUser() user: LoginUserInfo) {
    return this.service.reportePendientes(user.empresa_id);
  }

  @Get('reportes/diferencias')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_VER')
  @ApiOperation({ summary: 'Reporte: Diferencias detectadas en verificación' })
  @ApiQuery({ name: 'nivel', required: false, description: 'menor | mayor' })
  @ApiQuery({ name: 'fecha_desde', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'fecha_hasta', required: false, description: 'YYYY-MM-DD' })
  reporteDiferencias(
    @GetUser() user: LoginUserInfo,
    @Query('nivel') nivel?: string,
    @Query('fecha_desde') fecha_desde?: string,
    @Query('fecha_hasta') fecha_hasta?: string,
  ) {
    return this.service.reporteDiferencias(user.empresa_id, { nivel, fecha_desde, fecha_hasta });
  }

  @Get('reportes/comisiones-liquidar')
  @RequirePermission('COBRANZAS', 'COB_COM_LIQUIDACION_VER')
  @ApiOperation({ summary: 'Reporte: Comisiones aprobadas pendientes de liquidación' })
  @ApiQuery({ name: 'cobrador_id', required: false })
  reporteComisionesLiquidar(
    @GetUser() user: LoginUserInfo,
    @Query('cobrador_id') cobradorId?: string,
  ) {
    return this.service.reporteComisionesLiquidar(user.empresa_id, cobradorId);
  }

  @Post()
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_CREAR')
  @ApiOperation({ summary: 'Crear rendición (BORRADOR)' })
  create(@GetUser() user: LoginUserInfo, @Body() dto: CreateRendicionDto) {
    return this.service.create(user.empresa_id, user.id, dto);
  }

  @Post(':id/enviar-tesoreria')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_CREAR')
  @ApiOperation({ summary: 'Enviar rendición a tesorería (BORRADOR/OBSERVADO → PENDIENTE)' })
  enviarTesoreria(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Body() dto: EnviarTesoreriaDto,
  ) {
    return this.service.enviarATesoreria(user.empresa_id, id, user.id, dto);
  }

  @Patch(':id/medios-pago/:mpId/verificar')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_APROBAR')
  @ApiOperation({ summary: 'Verificar un medio de pago de la rendición (Tesorería)' })
  verificarMedioPago(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Param('mpId') mpId: string,
    @Body() dto: VerificarMedioPagoDto,
  ) {
    return this.service.verificarMedioPago(user.empresa_id, id, mpId, user.id, dto);
  }

  @Post(':id/aprobar')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_APROBAR')
  @ApiOperation({ summary: 'Aprobar rendición (PENDIENTE → APROBADO)' })
  aprobar(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Body() dto: AprobarRendicionDto,
  ) {
    return this.service.aprobar(user.empresa_id, id, user.id, dto);
  }

  @Post(':id/rechazar')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_APROBAR')
  @ApiOperation({ summary: 'Observar o rechazar rendición (PENDIENTE → OBSERVADO/RECHAZADO)' })
  rechazar(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Body() dto: RechazarRendicionDto,
  ) {
    return this.service.rechazar(user.empresa_id, id, user.id, dto);
  }

  @Get()
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_VER')
  @ApiOperation({ summary: 'Listar rendiciones con filtros y paginación' })
  @ApiQuery({ name: 'cobrador_id', required: false })
  @ApiQuery({ name: 'fecha_desde', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'fecha_hasta', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'estado', required: false, enum: ESTADOS_RENDICION as unknown as string[] })
  @ApiQuery({ name: 'moneda_id', required: false })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  findAll(
    @GetUser() user: LoginUserInfo,
    @Query('cobrador_id') cobrador_id?: string,
    @Query('fecha_desde') fecha_desde?: string,
    @Query('fecha_hasta') fecha_hasta?: string,
    @Query('estado') estado?: string,
    @Query('moneda_id') moneda_id?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    return this.service.findAll(user.empresa_id, {
      cobrador_id,
      fecha_desde,
      fecha_hasta,
      estado,
      moneda_id,
      page: page ? parseInt(page) : 1,
      limit: limit ? parseInt(limit) : 20,
    });
  }

  @Get(':id')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_VER')
  @ApiOperation({ summary: 'Detalle de una rendición' })
  findOne(@GetUser() user: LoginUserInfo, @Param('id') id: string) {
    return this.service.findOne(user.empresa_id, id);
  }

  @Patch(':id/revisar')
  @RequirePermission('COBRANZAS', 'COB_RND_RENDICION_APROBAR')
  @ApiOperation({
    summary: 'Legacy: revisar (deprecated). Usar /aprobar, /rechazar.',
    deprecated: true,
  })
  revisar(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Body() dto: RevisarRendicionDto,
  ) {
    return this.service.revisar(user.empresa_id, id, user.id, dto);
  }
}
