import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseUUIDPipe,
  Patch,
  Post,
  UseGuards,
  ValidationPipe,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import { RequireSubmodulo } from 'src/auth/decorators/require-submodulo.decorator';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import { SubmoduloGuard } from 'src/auth/guards/submodulo.guard';
import { EmitirInformeDto, GenerarInformeDto } from '../fideicomiso/dto/fideicomiso.dto';
import { FideicomisoInmService } from '../fideicomiso/fideicomiso.service';
import {
  CreateAporteDto,
  CreateCanjeDto,
  CreateDistribucionDto,
  CreateInversorDto,
  MotivoInversoresDto,
  PagarLineaDto,
  UpdateInversorDto,
} from './dto/inversores.dto';
import { InversoresInmService } from './inversores.service';

@ApiTags('Inmobiliario · Inversores y fideicomiso')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), SubmoduloGuard)
@RequireSubmodulo('INM_INVERSORES')
@Controller({ path: 'inmobiliario', version: '1' })
export class InversoresInmController {
  constructor(
    private readonly inversores: InversoresInmService,
    private readonly fideicomiso: FideicomisoInmService,
  ) {}

  // --------------------------------------------------------------- inversores

  @Get('proyectos/:id/inversores')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_INVERSOR_VER')
  @ApiOperation({ summary: 'Inversores del proyecto con su estado de cuenta y totales' })
  resumen(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.inversores.resumenProyecto(id, user.empresa_id);
  }

  @Get('inversores/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_INVERSOR_VER')
  @ApiOperation({ summary: 'Estado de cuenta del inversor' })
  estadoCuenta(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.inversores.estadoCuenta(id, user.empresa_id);
  }

  @Post('inversores')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_INVERSOR_CREAR')
  crear(@Body(ValidationPipe) dto: CreateInversorDto, @GetUser() user: LoginUserInfo) {
    return this.inversores.crear(dto, user.empresa_id, user.id);
  }

  @Patch('inversores/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_INVERSOR_EDITAR')
  actualizar(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: UpdateInversorDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.inversores.actualizar(id, dto, user.empresa_id, user.id);
  }

  @Delete('inversores/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_INVERSOR_EDITAR')
  darDeBaja(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.inversores.darDeBaja(id, user.empresa_id, user.id);
  }

  @Post('inversores/aportes')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_APORTE_CREAR')
  crearAporte(@Body(ValidationPipe) dto: CreateAporteDto, @GetUser() user: LoginUserInfo) {
    return this.inversores.crearAporte(dto, user.empresa_id, user.id);
  }

  @Post('inversores/aportes/:id/anular')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_APORTE_ANULAR')
  anularAporte(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: MotivoInversoresDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.inversores.anularAporte(id, dto, user.empresa_id, user.id);
  }

  @Post('inversores/canjes')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_APORTE_CREAR')
  @ApiOperation({ summary: 'Entrega una unidad al inversor en canje (la unidad queda bloqueada)' })
  crearCanje(@Body(ValidationPipe) dto: CreateCanjeDto, @GetUser() user: LoginUserInfo) {
    return this.inversores.crearCanje(dto, user.empresa_id, user.id);
  }

  @Post('inversores/canjes/:id/anular')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_APORTE_ANULAR')
  anularCanje(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: MotivoInversoresDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.inversores.anularCanje(id, dto, user.empresa_id, user.id);
  }

  // ------------------------------------------------------------ distribuciones

  @Get('proyectos/:id/distribuciones')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_INVERSOR_VER')
  distribuciones(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.inversores.listarDistribuciones(id, user.empresa_id);
  }

  @Post('distribuciones')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_DISTRIBUCION_CREAR')
  @ApiOperation({ summary: 'Distribución en borrador, repartida por participación' })
  crearDistribucion(@Body(ValidationPipe) dto: CreateDistribucionDto, @GetUser() user: LoginUserInfo) {
    return this.inversores.crearDistribucion(dto, user.empresa_id, user.id);
  }

  @Post('distribuciones/:id/aprobar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_DISTRIBUCION_APROBAR')
  aprobarDistribucion(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.inversores.aprobarDistribucion(id, user.empresa_id, user.id);
  }

  @Post('distribuciones/:id/anular')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_DISTRIBUCION_APROBAR')
  anularDistribucion(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: MotivoInversoresDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.inversores.anularDistribucion(id, dto, user.empresa_id, user.id);
  }

  @Post('distribuciones/lineas/:id/pagar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_DISTRIBUCION_PAGAR')
  @ApiOperation({ summary: 'Registra el pago a un inversor (el pago se hace por Tesorería)' })
  pagarLinea(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: PagarLineaDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.inversores.pagarLinea(id, dto, user.empresa_id, user.id);
  }

  // ---------------------------------------------------------------- fideicomiso

  @Get('proyectos/:id/informes-fideicomiso')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_FIDEICOMISO_VER')
  informes(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.fideicomiso.listar(id, user.empresa_id);
  }

  @Get('informes-fideicomiso/:id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_FIDEICOMISO_VER')
  informe(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.fideicomiso.detalle(id, user.empresa_id);
  }

  @Post('proyectos/:id/informes-fideicomiso')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_FIDEICOMISO_GENERAR')
  @ApiOperation({ summary: 'Genera (o recalcula, si está en borrador) el informe del período' })
  generar(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: GenerarInformeDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.fideicomiso.generar(id, dto, user.empresa_id, user.id);
  }

  @Post('informes-fideicomiso/:id/emitir')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_INV_FIDEICOMISO_EMITIR')
  @ApiOperation({ summary: 'Emite el informe: se recalcula por última vez y queda congelado' })
  emitir(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: EmitirInformeDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.fideicomiso.emitir(id, dto, user.empresa_id, user.id);
  }
}
