import { Body, Controller, Get, Param, Post, Query, Res, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiQuery, ApiTags } from '@nestjs/swagger';
import type { Response } from 'express';
import { RequireModule } from 'src/auth/decorators/require-module.decorator';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import { ModuleGuard } from 'src/auth/guards/module.guard';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import type { LoginUserInfo } from '../auth/dto/login.dto';
import { GetUser } from '../auth/get-user.decorator';
import { assertRangoFechas } from '../common/utils/fecha-rango.util';
import { ReportesProveedorService } from './reportes-proveedor.service';

@ApiTags('Reportes-Proveedor')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), ModuleGuard)
@RequireModule('INVENTARIO')
@Controller({ version: '1', path: 'reportes/proveedor' })
export class ReportesProveedorController {
  constructor(private readonly service: ReportesProveedorService) {}

  @Get(':id/vencidos')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_VENCIDOS_PROVEEDOR_VER')
  @ApiQuery({ name: 'desde', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'hasta', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'depositoId', required: false })
  async vencidos(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('depositoId') depositoId?: string,
  ) {
    assertRangoFechas(desde, hasta);
    return this.service.vencidos(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
      deposito_id: depositoId,
    }, user.id);
  }

  @Get(':id/proximos-vencer')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_PROXIMOS_VENCER_VER')
  @ApiQuery({ name: 'dias', required: false, enum: [30, 60, 90] })
  @ApiQuery({ name: 'depositoId', required: false })
  async proximosVencer(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Query('dias') dias?: string,
    @Query('depositoId') depositoId?: string,
  ) {
    const diasNum = dias ? (parseInt(dias, 10) as 30 | 60 | 90) : 90;
    return this.service.proximosVencer(user.empresa_id, id, {
      dias: diasNum,
      deposito_id: depositoId,
    }, user.id);
  }

  @Get(':id/stock-marcas')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_STOCK_POR_PROVEEDOR_VER')
  @ApiQuery({ name: 'depositoId', required: false })
  async stockMarcas(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Query('depositoId') depositoId?: string,
  ) {
    return this.service.stockMarcas(user.empresa_id, id, { deposito_id: depositoId }, user.id);
  }

  @Get(':id/resumen')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_VENCIDOS_PROVEEDOR_VER')
  async resumen(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.resumen(user.empresa_id, id);
  }

  @Get(':id/marcas-compradas')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_VENCIDOS_PROVEEDOR_VER')
  @ApiQuery({ name: 'desde', required: false, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'hasta', required: false, description: 'YYYY-MM-DD' })
  async marcasCompradas(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
  ) {
    assertRangoFechas(desde, hasta);
    return this.service.marcasCompradas(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
    }, user.id);
  }

  @Get(':id/ventas-por-marca')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_VENCIDOS_PROVEEDOR_VER')
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  @ApiQuery({ name: 'modo', required: false, enum: ['vinculo', 'lote'] })
  @ApiQuery({ name: 'soloPreferente', required: false, type: Boolean })
  async ventasPorMarca(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('modo') modo?: 'vinculo' | 'lote',
    @Query('soloPreferente') soloPreferente?: string,
  ) {
    assertRangoFechas(desde, hasta);
    return this.service.ventasPorMarca(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
      modo: modo === 'lote' ? 'lote' : 'vinculo',
      soloPreferente: soloPreferente === 'true',
    }, user.id);
  }

  @Get(':id/capabilities')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_VENCIDOS_PROVEEDOR_VER')
  async capabilities(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.capabilities(user.empresa_id, id, user.id);
  }

  @Get(':id/vencidos/exportar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_EXPORTAR')
  async exportarVencidos(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('depositoId') depositoId?: string,
  ) {
    const buffer = await this.service.exportarVencidosExcel(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
      deposito_id: depositoId,
    });
    const fileName = `vencidos-proveedor-${new Date().toISOString().substring(0, 10)}.xlsx`;
    res.setHeader(
      'Content-Type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    );
    res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
    res.send(buffer);
  }

  @Get(':id/vencidos/pdf')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_EXPORTAR')
  async exportarVencidosPDF(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('depositoId') depositoId?: string,
  ) {
    const buffer = await this.service.exportarVencidosPDF(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
      deposito_id: depositoId,
    });
    const fileName = `vencidos-proveedor-${new Date().toISOString().substring(0, 10)}.pdf`;
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', `inline; filename="${fileName}"`);
    res.send(buffer);
  }

  @Get(':id/marcas-compradas/exportar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_EXPORTAR')
  async exportarMarcasCompradas(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
  ) {
    const buffer = await this.service.exportarMarcasCompradasExcel(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
    });
    res.setHeader(
      'Content-Type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    );
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="marcas-compradas-${new Date().toISOString().substring(0, 10)}.xlsx"`,
    );
    res.send(buffer);
  }

  @Get(':id/marcas-compradas/pdf')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_EXPORTAR')
  async exportarMarcasCompradasPDF(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
  ) {
    const buffer = await this.service.exportarMarcasCompradasPDF(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
    });
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader(
      'Content-Disposition',
      `inline; filename="marcas-compradas-${new Date().toISOString().substring(0, 10)}.pdf"`,
    );
    res.send(buffer);
  }

  @Get(':id/ventas-por-marca/exportar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_EXPORTAR')
  async exportarVentasPorMarca(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('modo') modo?: 'vinculo' | 'lote',
    @Query('soloPreferente') soloPreferente?: string,
  ) {
    const buffer = await this.service.exportarVentasPorMarcaExcel(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
      modo: modo === 'lote' ? 'lote' : 'vinculo',
      soloPreferente: soloPreferente === 'true',
    });
    res.setHeader(
      'Content-Type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    );
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="ventas-por-marca-${new Date().toISOString().substring(0, 10)}.xlsx"`,
    );
    res.send(buffer);
  }

  @Get(':id/ventas-por-marca/pdf')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_EXPORTAR')
  async exportarVentasPorMarcaPDF(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
    @Query('desde') desde?: string,
    @Query('hasta') hasta?: string,
    @Query('modo') modo?: 'vinculo' | 'lote',
    @Query('soloPreferente') soloPreferente?: string,
  ) {
    const buffer = await this.service.exportarVentasPorMarcaPDF(user.empresa_id, id, {
      desde: desde || undefined,
      hasta: hasta || undefined,
      modo: modo === 'lote' ? 'lote' : 'vinculo',
      soloPreferente: soloPreferente === 'true',
    });
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader(
      'Content-Disposition',
      `inline; filename="ventas-por-marca-${new Date().toISOString().substring(0, 10)}.pdf"`,
    );
    res.send(buffer);
  }

  @Post(':id/enviar-email')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_RPR_REPORTE_ENVIAR_EMAIL')
  async enviarEmail(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Body() body: { desde?: string; hasta?: string; depositoId?: string; email?: string },
  ) {
    return this.service.enviarVencidosEmail(user.empresa_id, id, {
      desde: body.desde || undefined,
      hasta: body.hasta || undefined,
      deposito_id: body.depositoId,
      emailOverride: body.email,
    });
  }
}
