import { Body, Controller, Get, Param, Post, Query, Res, UseGuards, ValidationPipe } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Response } from 'express';
import { RequireModule, RequirePermission } from 'src/auth/decorators';
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 { ContabilidadConciliacionService } from './contabilidad-conciliacion.service';

@ApiTags('Conciliación Contable')
@Controller({ path: 'contabilidad/conciliacion', version: '1' })
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('CONTABILIDAD')
@ApiBearerAuth()
export class ContabilidadConciliacionController {
  constructor(private readonly service: ContabilidadConciliacionService) {}

  @Get('registry')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({ summary: 'Lista los orígenes contabilizables declarados' })
  registry() {
    return this.service.listarRegistry();
  }

  @Get('estado')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({ summary: 'Estado del módulo Contabilidad para la empresa' })
  estado(@GetUser() user: LoginUserInfo) {
    return this.service.estadoModuloContabilidad(user.empresa_id);
  }

  @Get('resumen')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({
    summary: 'Resumen de asientos pendientes agrupado por origen',
  })
  resumen(
    @GetUser() user: LoginUserInfo,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('origen_tipos') origenTipos?: string,
  ) {
    const tipos = origenTipos
      ? origenTipos.split(',').map((t) => t.trim()).filter(Boolean)
      : undefined;
    return this.service.resumen(user.empresa_id, {
      desde,
      hasta,
      origen_tipos: tipos,
    });
  }

  @Get('resumen/pdf')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({ summary: 'PDF del reporte de conciliación (msv-kude)' })
  async resumenPDF(
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('origen_tipos') origenTipos?: string,
  ) {
    const tipos = origenTipos
      ? origenTipos.split(',').map((t) => t.trim()).filter(Boolean)
      : undefined;
    const { pdfBuffer, filename } = await this.service.generarPDFReporte(user.empresa_id, {
      desde,
      hasta,
      origen_tipos: tipos,
    });
    res.set({
      'Content-Type': 'application/pdf',
      'Content-Disposition': `inline; filename="${filename}"`,
      'Content-Length': String(pdfBuffer.length),
    });
    res.end(pdfBuffer);
  }

  @Get('motivos')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({ summary: 'Catálogo de motivos posibles con su resolución' })
  motivos() {
    return this.service.listarMotivos();
  }

  @Get('diagnostico/:origenTipo/:id')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({ summary: 'Diagnóstico de un registro pendiente' })
  diagnostico(
    @GetUser() user: LoginUserInfo,
    @Param('origenTipo') origenTipo: string,
    @Param('id') id: string,
  ) {
    return this.service.diagnosticarRegistro(user.empresa_id, origenTipo, id);
  }

  @Post('regenerar-todo')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_REGENERAR')
  @ApiOperation({ summary: 'Regenera todos los orígenes activos que tengan pendientes' })
  regenerarTodo(
    @GetUser() user: LoginUserInfo,
    @Body(ValidationPipe) body: { desde?: string; hasta?: string } = {},
  ) {
    return this.service.regenerarTodos(
      user.empresa_id,
      { desde: body?.desde, hasta: body?.hasta },
      user.id,
    );
  }

  @Post('re-seed-registry')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_REGENERAR')
  @ApiOperation({
    summary: 'Re-sincroniza el registry desde el seed hardcodeado (idempotente)',
  })
  async reSeedRegistry() {
    await this.service.sincronizarRegistry();
    return { status: 'ok', message: 'Registry sincronizado' };
  }

  @Post('regenerar/:origenTipo/:id')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_REGENERAR')
  @ApiOperation({ summary: 'Regenera el asiento de un único registro pendiente' })
  regenerarUno(
    @GetUser() user: LoginUserInfo,
    @Param('origenTipo') origenTipo: string,
    @Param('id') id: string,
  ) {
    return this.service.regenerarUno(user.empresa_id, origenTipo, id, user.id);
  }

  @Post('regenerar/:origenTipo')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_REGENERAR')
  @ApiOperation({ summary: 'Regenera en lote los pendientes de un origen (máx 500)' })
  regenerarLote(
    @GetUser() user: LoginUserInfo,
    @Param('origenTipo') origenTipo: string,
    @Body(ValidationPipe) body: { ids?: string[]; desde?: string; hasta?: string } = {},
  ) {
    return this.service.regenerarLote(
      user.empresa_id,
      {
        origen_tipo: origenTipo,
        ids: body?.ids,
        desde: body?.desde,
        hasta: body?.hasta,
      },
      user.id,
    );
  }

  @Post('diagnostico-lote/:origenTipo')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({ summary: 'Diagnóstico en lote (mismo origen)' })
  diagnosticoLote(
    @GetUser() user: LoginUserInfo,
    @Param('origenTipo') origenTipo: string,
    @Body(ValidationPipe) body: { ids: string[] },
  ) {
    return this.service.diagnosticarLote(user.empresa_id, origenTipo, body?.ids ?? []);
  }

  @Get('detalle/:origenTipo')
  @RequirePermission('CONTABILIDAD', 'CONT_CONC_PENDIENTES_VER')
  @ApiOperation({
    summary: 'Detalle paginado de registros pendientes para un origen',
  })
  detalle(
    @GetUser() user: LoginUserInfo,
    @Param('origenTipo') origenTipo: string,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('limit') limit?: string,
  ) {
    return this.service.detalle(user.empresa_id, origenTipo, {
      desde,
      hasta,
      limit: limit ? Number(limit) : undefined,
    });
  }
}
