import { Controller, Get, Param, Query, Res, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import type { Response } from 'express';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import { GetUser } from 'src/auth/get-user.decorator';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import { ReportesService } from '../services/reportes.service';

@ApiTags('Contabilidad - Reportes')
@Controller({ path: 'contabilidad/reportes', version: '1' })
@UseGuards(AuthGuard('jwt'), PermissionGuard)
@RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_VER')
@ApiBearerAuth()
export class ReportesController {
  constructor(private readonly reportes: ReportesService) {}

  @Get('libro-diario')
  @ApiOperation({ summary: 'Libro Diario — asientos confirmados en rango' })
  @ApiQuery({ name: 'periodoId', required: false })
  @ApiQuery({ name: 'desde', required: false, example: '2026-01-01' })
  @ApiQuery({ name: 'hasta', required: false, example: '2026-12-31' })
  @ApiQuery({ name: 'centroCostoId', required: false })
  libroDiario(@GetUser() user: LoginUserInfo, @Query('periodoId') periodoId?: string, @Query('desde') desde?: string, @Query('hasta') hasta?: string, @Query('centroCostoId') centroCostoId?: string) {
    return this.reportes.libroDiario(user.empresa_id, { periodoId, desde, hasta, centroCostoId });
  }

  @Get('libro-diario/pdf')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Libro Diario — descarga PDF (via msv-kude)' })
  async libroDiarioPdf(@GetUser() user: LoginUserInfo, @Res() res: Response, @Query('periodoId') periodoId?: string, @Query('desde') desde?: string, @Query('hasta') hasta?: string, @Query('titulo') titulo?: string, @Query('periodo') periodo?: string, @Query('centroCostoId') centroCostoId?: string) {
    const buffer = await this.reportes.libroDiarioPdf(user.empresa_id, { periodoId, desde, hasta, titulo, periodo, centroCostoId });
    res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': 'inline; filename="libro-diario.pdf"' });
    res.send(buffer);
  }

  @Get('libro-diario/excel')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Libro Diario — descarga Excel' })
  async libroDiarioExcel(@GetUser() user: LoginUserInfo, @Res() res: Response, @Query('periodoId') periodoId?: string, @Query('desde') desde?: string, @Query('hasta') hasta?: string, @Query('centroCostoId') centroCostoId?: string) {
    const buffer = await this.reportes.libroDiarioExcel(user.empresa_id, { periodoId, desde, hasta, centroCostoId });
    res.set({ 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-Disposition': 'attachment; filename="libro-diario.xlsx"' });
    res.send(buffer);
  }

  @Get('libro-mayor/:cuentaId')
  @ApiOperation({ summary: 'Libro Mayor — movimientos de una cuenta con saldo acumulado' })
  @ApiQuery({ name: 'periodoId', required: false })
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  @ApiQuery({ name: 'centroCostoId', required: false })
  libroMayor(@GetUser() user: LoginUserInfo, @Param('cuentaId') cuentaId: string, @Query('periodoId') periodoId?: string, @Query('desde') desde?: string, @Query('hasta') hasta?: string, @Query('centroCostoId') centroCostoId?: string) {
    return this.reportes.libroMayor(user.empresa_id, cuentaId, { periodoId, desde, hasta, centroCostoId });
  }

  @Get('balance-comprobacion')
  @ApiOperation({ summary: 'Balance de Comprobación — sumas y saldos por cuenta' })
  @ApiQuery({ name: 'periodoId', required: false })
  @ApiQuery({ name: 'ejercicioId', required: false })
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  balanceComprobacion(@GetUser() user: LoginUserInfo, @Query('periodoId') periodoId?: string, @Query('ejercicioId') ejercicioId?: string, @Query('desde') desde?: string, @Query('hasta') hasta?: string) {
    return this.reportes.balanceComprobacion(user.empresa_id, { periodoId, ejercicioId, desde, hasta });
  }

  @Get('libro-mayor/:cuentaId/pdf')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Libro Mayor — descarga PDF (via msv-kude)' })
  async libroMayorPdf(@GetUser() user: LoginUserInfo, @Res() res: Response, @Param('cuentaId') cuentaId: string, @Query('periodoId') periodoId?: string, @Query('desde') desde?: string, @Query('hasta') hasta?: string, @Query('centroCostoId') centroCostoId?: string) {
    const buffer = await this.reportes.libroMayorPdf(user.empresa_id, cuentaId, { periodoId, desde, hasta, centroCostoId });
    res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': 'inline; filename="libro-mayor.pdf"' });
    res.send(buffer);
  }

  @Get('balance-comprobacion/pdf')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Balance de Comprobación — descarga PDF (via msv-kude)' })
  async balanceComprobacionPdf(@GetUser() user: LoginUserInfo, @Res() res: Response, @Query('periodoId') periodoId?: string, @Query('ejercicioId') ejercicioId?: string, @Query('titulo') titulo?: string, @Query('periodo') periodo?: string) {
    const buffer = await this.reportes.balanceComprobacionPdf(user.empresa_id, { periodoId, ejercicioId, titulo, periodo });
    res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': 'inline; filename="balance-comprobacion.pdf"' });
    res.send(buffer);
  }

  @Get('balance-comprobacion/excel')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Balance de Comprobación — descarga Excel' })
  async balanceComprobacionExcel(@GetUser() user: LoginUserInfo, @Res() res: Response, @Query('periodoId') periodoId?: string, @Query('ejercicioId') ejercicioId?: string) {
    const buffer = await this.reportes.balanceComprobacionExcel(user.empresa_id, { periodoId, ejercicioId });
    res.set({ 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-Disposition': 'attachment; filename="balance-comprobacion.xlsx"' });
    res.send(buffer);
  }

  @Get('estado-resultados')
  @ApiOperation({ summary: 'Estado de Resultados — ingresos, costos, gastos y utilidad' })
  @ApiQuery({ name: 'ejercicioId', required: false })
  @ApiQuery({ name: 'periodoId', required: false })
  @ApiQuery({ name: 'centroCostoId', required: false })
  estadoResultados(@GetUser() user: LoginUserInfo, @Query('ejercicioId') ejercicioId?: string, @Query('periodoId') periodoId?: string, @Query('centroCostoId') centroCostoId?: string) {
    return this.reportes.estadoResultados(user.empresa_id, { ejercicioId, periodoId, centroCostoId });
  }

  @Get('estado-resultados/pdf')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Estado de Resultados — descarga PDF (via msv-kude)' })
  @ApiQuery({ name: 'centroCostoId', required: false })
  async estadoResultadosPdf(@GetUser() user: LoginUserInfo, @Res() res: Response, @Query('ejercicioId') ejercicioId?: string, @Query('periodoId') periodoId?: string, @Query('titulo') titulo?: string, @Query('periodo') periodo?: string, @Query('centroCostoId') centroCostoId?: string) {
    const buffer = await this.reportes.estadoResultadosPdf(user.empresa_id, { ejercicioId, periodoId, titulo, periodo, centroCostoId });
    res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': 'inline; filename="estado-resultados.pdf"' });
    res.send(buffer);
  }

  @Get('balance-general')
  @ApiOperation({ summary: 'Balance General — activos, pasivos y patrimonio' })
  @ApiQuery({ name: 'ejercicioId', required: false })
  @ApiQuery({ name: 'periodoId', required: false })
  balanceGeneral(@GetUser() user: LoginUserInfo, @Query('ejercicioId') ejercicioId?: string, @Query('periodoId') periodoId?: string) {
    return this.reportes.balanceGeneral(user.empresa_id, { ejercicioId, periodoId });
  }

  @Get('balance-general/pdf')
  @RequirePermission('CONTABILIDAD', 'CONT_REP_REPORTE_EXPORTAR')
  @ApiOperation({ summary: 'Balance General — descarga PDF (via msv-kude)' })
  async balanceGeneralPdf(@GetUser() user: LoginUserInfo, @Res() res: Response, @Query('ejercicioId') ejercicioId?: string, @Query('periodoId') periodoId?: string, @Query('titulo') titulo?: string, @Query('periodo') periodo?: string) {
    const buffer = await this.reportes.balanceGeneralPdf(user.empresa_id, { ejercicioId, periodoId, titulo, periodo });
    res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': 'inline; filename="balance-general.pdf"' });
    res.send(buffer);
  }
}
