import {
  BadRequestException,
  Body,
  Controller,
  Get,
  Param,
  Patch,
  Post,
  Query,
  Res,
  UploadedFile,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiOperation, ApiTags } from '@nestjs/swagger';
import type { Response } from 'express';
import * as XLSX from 'xlsx';
import { RequireModule } from '../../auth/decorators/require-module.decorator';
import { RequirePermission } from '../../auth/decorators/require-permission.decorator';
import type { LoginUserInfo } from '../../auth/dto/login.dto';
import { GetUser } from '../../auth/get-user.decorator';
import { ModuleGuard } from '../../auth/guards/module.guard';
import { PermissionGuard } from '../../auth/guards/permission.guard';
import { AnularPlanillaDto, ImportarPlanillaDto, QueryPlanillasDto } from '../dto/planillas.dto';
import { PlanillasService } from '../services/planillas.service';

@ApiTags('RRHH - Planillas externas (Excel/CSV)')
@Controller({ path: 'rrhh/planillas-externas', version: '1' })
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('RRHH')
@ApiBearerAuth()
export class PlanillasController {
  constructor(private readonly service: PlanillasService) {}

  @Get()
  @RequirePermission('RRHH', 'RH_PLA_PLANILLA_VER')
  @ApiOperation({ summary: 'Listar planillas externas importadas' })
  listar(@GetUser() user: LoginUserInfo, @Query() query: QueryPlanillasDto) {
    return this.service.listar(user.empresa_id, query);
  }

  @Get('plantilla')
  @RequirePermission('RRHH', 'RH_PLA_PLANILLA_EXPORTAR')
  @ApiOperation({
    summary: 'Descargar plantilla Excel de ejemplo',
    description: 'Hoja "Planilla" con columnas: numero_empleado, codigo_concepto, tipo, monto, observacion',
  })
  descargarPlantilla(@Res() res: Response) {
    const wb = XLSX.utils.book_new();
    const ws = XLSX.utils.aoa_to_sheet([
      ['numero_empleado', 'codigo_concepto', 'tipo', 'monto', 'observacion'],
      ['EMP-0001', 'COMISION_VENTAS', 'INGRESO', 500000, 'Comisión noviembre'],
      ['EMP-0002', 'BONO_DESEMPENO', 'INGRESO', 300000, 'Cumple objetivos Q4'],
      ['EMP-0003', 'DESCUENTO_AUSENCIA', 'EGRESO', 80000, 'Falta sin justificar 12-nov'],
    ]);
    XLSX.utils.book_append_sheet(wb, ws, 'Planilla');
    const buffer = XLSX.write(wb, { type: 'buffer', bookType: 'xlsx' });
    res.setHeader(
      'Content-Type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    );
    res.setHeader('Content-Disposition', 'attachment; filename="planilla_externa_rrhh.xlsx"');
    res.send(buffer);
  }

  @Get(':id')
  @RequirePermission('RRHH', 'RH_PLA_PLANILLA_VER')
  @ApiOperation({ summary: 'Obtener planilla con detalles y errores' })
  obtener(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.obtener(id, user.empresa_id);
  }

  @Post('importar')
  @RequirePermission('RRHH', 'RH_PLA_PLANILLA_GENERAR')
  @UseInterceptors(FileInterceptor('archivo', { limits: { fileSize: 10 * 1024 * 1024 } }))
  @ApiOperation({
    summary: 'Importar planilla desde Excel/CSV',
    description:
      'Sube .xlsx, .xls o .csv con columnas: numero_empleado, codigo_concepto, tipo (INGRESO/EGRESO), monto, observacion (opcional). ' +
      'Cada fila se valida; las inválidas quedan registradas en errores_importacion sin bloquear las válidas.',
  })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        archivo: { type: 'string', format: 'binary' },
        nombre: { type: 'string' },
        periodo_anio: { type: 'integer' },
        periodo_mes: { type: 'integer' },
      },
    },
  })
  importar(
    @GetUser() user: LoginUserInfo,
    @Body() dto: ImportarPlanillaDto,
    @UploadedFile() archivo: Express.Multer.File,
  ) {
    if (!archivo) throw new BadRequestException('Debe adjuntar el archivo en el campo "archivo"');
    return this.service.importar(user.empresa_id, dto, archivo, user.id);
  }

  @Patch(':id/anular')
  @RequirePermission('RRHH', 'RH_PLA_PLANILLA_GENERAR')
  @ApiOperation({ summary: 'Anular planilla (no permitido si ya fue aplicada a liquidación)' })
  anular(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Body() dto: AnularPlanillaDto,
  ) {
    return this.service.anular(id, user.empresa_id, dto, user.id);
  }
}
