import {
  BadRequestException,
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Res,
  UploadedFile,
  UseGuards,
  UseInterceptors,
  ValidationPipe,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
import type { LoginUserInfo } from '../auth/dto/login.dto';
import { GetUser } from '../auth/get-user.decorator';
import { RequirePermission } from '../auth/decorators/require-permission.decorator';
import { PermissionGuard } from '../auth/guards/permission.guard';
import { ConciliacionBancariaIaService } from './conciliacion-bancaria-ia.service';
import { CrearSesionDto } from './dto/crear-sesion.dto';
import { ConciliarDto } from './dto/conciliar.dto';
import { MatchManualDto } from './dto/match-manual.dto';
import { CrearMovimientoDto, EditarMovimientoDto } from './dto/movimiento.dto';

const MODULO = 'CONCILIACION_IA';
const UPLOAD_OPTS = { limits: { fileSize: 15 * 1024 * 1024 } };

@Controller({ version: '1', path: 'conciliacion-bancaria-ia' })
@UseGuards(AuthGuard('jwt'))
export class ConciliacionBancariaIaController {
  constructor(private readonly service: ConciliacionBancariaIaService) {}

  @Get('sesiones')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  listarSesiones(@GetUser() user: LoginUserInfo) {
    return this.service.listarSesiones(user.empresa_id);
  }

  @Post('sesiones')
  @RequirePermission(MODULO, 'CONC_IA_CREAR')
  @UseGuards(PermissionGuard)
  crearSesion(@GetUser() user: LoginUserInfo, @Body(ValidationPipe) dto: CrearSesionDto) {
    return this.service.crearSesion(user.empresa_id, user.id, dto);
  }

  @Post('sesiones/:id/archivo-propio')
  @RequirePermission(MODULO, 'CONC_IA_CARGAR')
  @UseGuards(PermissionGuard)
  @UseInterceptors(FileInterceptor('file', UPLOAD_OPTS))
  cargarArchivoPropio(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @UploadedFile() file: Express.Multer.File,
  ) {
    if (!file) throw new BadRequestException('Adjuntá el archivo en el campo "file".');
    return this.service.cargarArchivo(user.empresa_id, id, 'PROPIO', file);
  }

  @Post('sesiones/:id/archivo-banco')
  @RequirePermission(MODULO, 'CONC_IA_CARGAR')
  @UseGuards(PermissionGuard)
  @UseInterceptors(FileInterceptor('file', UPLOAD_OPTS))
  cargarArchivoBanco(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @UploadedFile() file: Express.Multer.File,
  ) {
    if (!file) throw new BadRequestException('Adjuntá el archivo en el campo "file".');
    return this.service.cargarArchivo(user.empresa_id, id, 'BANCO', file);
  }

  // ── Preview editable (antes de conciliar): agregar / editar / borrar líneas ──
  @Post('sesiones/:id/movimiento')
  @RequirePermission(MODULO, 'CONC_IA_CARGAR')
  @UseGuards(PermissionGuard)
  agregarMovimiento(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Body(ValidationPipe) dto: CrearMovimientoDto) {
    return this.service.agregarMovimiento(user.empresa_id, id, dto);
  }

  @Patch('sesiones/:id/movimiento/:movId')
  @RequirePermission(MODULO, 'CONC_IA_CARGAR')
  @UseGuards(PermissionGuard)
  editarMovimiento(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Param('movId') movId: string,
    @Body(ValidationPipe) dto: EditarMovimientoDto,
  ) {
    return this.service.editarMovimiento(user.empresa_id, id, movId, dto);
  }

  @Delete('sesiones/:id/movimiento/:movId')
  @RequirePermission(MODULO, 'CONC_IA_CARGAR')
  @UseGuards(PermissionGuard)
  eliminarMovimiento(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Param('movId') movId: string) {
    return this.service.eliminarMovimiento(user.empresa_id, id, movId);
  }

  @Post('sesiones/:id/conciliar-auto')
  @RequirePermission(MODULO, 'CONC_IA_CONCILIAR')
  @UseGuards(PermissionGuard)
  conciliarAuto(
    @GetUser() user: LoginUserInfo,
    @Param('id') id: string,
    @Body(ValidationPipe) dto: ConciliarDto,
  ) {
    return this.service.conciliarAuto(user.empresa_id, id, dto);
  }

  @Get('sesiones/:id/resultado')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  getResultado(@GetUser() user: LoginUserInfo, @Param('id') id: string) {
    return this.service.getResultado(user.empresa_id, id);
  }

  // Estado para reanudar el asistente (sesión + preview de cada lado ya subido).
  @Get('sesiones/:id/estado')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  getEstado(@GetUser() user: LoginUserInfo, @Param('id') id: string) {
    return this.service.getEstadoParaReanudar(user.empresa_id, id);
  }

  // Resumen ejecutivo (IA) + hallazgos + asiento sugerido + ahorro de tiempo.
  @Get('sesiones/:id/resumen-ia')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  resumenIa(@GetUser() user: LoginUserInfo, @Param('id') id: string) {
    return this.service.resumenEjecutivo(user.empresa_id, id);
  }

  // Sugerencias de match para los pendientes que "casi cruzan".
  @Get('sesiones/:id/sugerencias-match')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  sugerenciasMatch(@GetUser() user: LoginUserInfo, @Param('id') id: string) {
    return this.service.sugerenciasMatch(user.empresa_id, id);
  }

  // Crear un match manual (aceptar una sugerencia o cruzar a mano).
  @Post('sesiones/:id/match-manual')
  @RequirePermission(MODULO, 'CONC_IA_CONCILIAR')
  @UseGuards(PermissionGuard)
  matchManual(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Body(ValidationPipe) dto: MatchManualDto) {
    return this.service.matchManual(user.empresa_id, id, dto.movimiento_propio_id, dto.movimiento_banco_id);
  }

  // Dashboard consolidado de todas las cuentas de la empresa.
  @Get('dashboard')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  dashboard(@GetUser() user: LoginUserInfo) {
    return this.service.dashboard(user.empresa_id);
  }

  // Consumo de IA del mes (para el chip del módulo). Accesible con permiso del módulo.
  @Get('consumo-ia')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  consumoIa(@GetUser() user: LoginUserInfo) {
    return this.service.consumoIa(user.empresa_id);
  }

  @Get('sesiones/:id/resultado/excel')
  @RequirePermission(MODULO, 'CONC_IA_VER')
  @UseGuards(PermissionGuard)
  async exportarExcel(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Res() res: Response) {
    const { buffer, filename } = await this.service.exportarExcel(user.empresa_id, id);
    res.set({
      'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'Content-Disposition': `attachment; filename="${filename}"`,
    });
    res.send(buffer);
  }

  // ── Acciones sobre el resultado (persisten y recalculan el %) ────────────────
  @Patch('sesiones/:id/movimiento/:movId/registrar')
  @RequirePermission(MODULO, 'CONC_IA_CONCILIAR')
  @UseGuards(PermissionGuard)
  registrarBanco(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Param('movId') movId: string) {
    return this.service.registrarMovimientoBanco(user.empresa_id, id, movId);
  }

  @Patch('sesiones/:id/movimiento/:movId/en-transito')
  @RequirePermission(MODULO, 'CONC_IA_CONCILIAR')
  @UseGuards(PermissionGuard)
  marcarEnTransito(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Param('movId') movId: string) {
    return this.service.marcarEnTransito(user.empresa_id, id, movId);
  }

  @Patch('sesiones/:id/match/:matchId/registrar-diferencia')
  @RequirePermission(MODULO, 'CONC_IA_CONCILIAR')
  @UseGuards(PermissionGuard)
  registrarDiferencia(@GetUser() user: LoginUserInfo, @Param('id') id: string, @Param('matchId') matchId: string) {
    return this.service.registrarDiferencia(user.empresa_id, id, matchId);
  }

  @Delete('sesiones/:id')
  @RequirePermission(MODULO, 'CONC_IA_ELIMINAR')
  @UseGuards(PermissionGuard)
  eliminarSesion(@GetUser() user: LoginUserInfo, @Param('id') id: string) {
    return this.service.eliminarSesion(user.empresa_id, id);
  }
}
