import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseUUIDPipe,
  Patch,
  Post,
  Query,
  UseGuards,
  ValidationPipe,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { inm_operacion_estado } from '@prisma/client';
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 {
  ActualizarCuotaDto,
  FirmarBoletoDto,
  LegajoDto,
  MotivoDto,
  ProrrogarReservaDto,
  ReservarDto,
  TitularDto,
} from './dto/operacion.dto';
import { OperacionesInmService } from './operaciones.service';

@ApiTags('Inmobiliario · Operaciones')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), SubmoduloGuard)
@RequireSubmodulo('INM_OPERACIONES')
@Controller({ path: 'inmobiliario/operaciones', version: '1' })
export class OperacionesInmController {
  constructor(private readonly service: OperacionesInmService) {}

  @Get()
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_VER')
  @ApiQuery({ name: 'proyecto_id', required: false })
  @ApiQuery({ name: 'estado', required: false, enum: inm_operacion_estado })
  @ApiQuery({ name: 'q', required: false })
  listar(
    @GetUser() user: LoginUserInfo,
    @Query('proyecto_id') proyecto_id?: string,
    @Query('estado') estado?: inm_operacion_estado,
    @Query('q') q?: string,
  ) {
    return this.service.listar(user.empresa_id, { proyecto_id, estado, q });
  }

  @Get(':id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_VER')
  @ApiOperation({ summary: 'Operación con titulares, cronograma, cobros y estado de cuenta' })
  detalle(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.service.detalle(id, user.empresa_id);
  }

  @Post('reservar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_RESERVA_CREAR')
  @ApiOperation({ summary: 'Reserva la unidad (409 si otro la tomó) y crea la cuota de seña' })
  reservar(@Body(ValidationPipe) dto: ReservarDto, @GetUser() user: LoginUserInfo) {
    return this.service.reservar(dto, user.empresa_id, user.id);
  }

  @Post(':id/prorrogar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_RESERVA_PRORROGAR')
  prorrogar(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: ProrrogarReservaDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.prorrogarReserva(id, dto, user.empresa_id, user.id);
  }

  @Post(':id/desistir')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_ANULAR')
  @ApiOperation({ summary: 'El comprador desiste antes del boleto: la unidad se libera' })
  desistir(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: MotivoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.desistir(id, dto, user.empresa_id, user.id);
  }

  @Post(':id/titulares')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_EDITAR')
  agregarTitular(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: TitularDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.agregarTitular(id, dto, user.empresa_id, user.id);
  }

  @Patch(':id/titulares/:titularId')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_EDITAR')
  actualizarTitular(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('titularId', ParseUUIDPipe) titularId: string,
    @Body(ValidationPipe) dto: TitularDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.actualizarTitular(id, titularId, dto, user.empresa_id, user.id);
  }

  @Delete(':id/titulares/:titularId')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_EDITAR')
  quitarTitular(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('titularId', ParseUUIDPipe) titularId: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.quitarTitular(id, titularId, user.empresa_id, user.id);
  }

  @Patch(':id/legajo')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_EDITAR')
  legajo(@Param('id', ParseUUIDPipe) id: string, @Body(ValidationPipe) dto: LegajoDto, @GetUser() user: LoginUserInfo) {
    return this.service.actualizarLegajo(id, dto, user.empresa_id, user.id);
  }

  @Post(':id/legajo/aprobar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_LEGAJO_APROBAR')
  aprobarLegajo(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.service.aprobarLegajo(id, user.empresa_id, user.id);
  }

  @Post(':id/legajo/observar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_LEGAJO_APROBAR')
  observarLegajo(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: MotivoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.observarLegajo(id, dto, user.empresa_id, user.id);
  }

  @Get(':id/boleto/preview')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_VER')
  @ApiQuery({ name: 'fecha', required: false })
  previsualizarBoleto(
    @Param('id', ParseUUIDPipe) id: string,
    @GetUser() user: LoginUserInfo,
    @Query('fecha') fecha?: string,
  ) {
    return this.service.previsualizarBoleto(id, user.empresa_id, fecha);
  }

  @Get(':id/boleto')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_VER')
  boleto(@Param('id', ParseUUIDPipe) id: string, @GetUser() user: LoginUserInfo) {
    return this.service.boleto(id, user.empresa_id);
  }

  @Post(':id/boleto')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_BOLETO_CONFIRMAR')
  @ApiOperation({ summary: 'Firma el boleto: 422 sin legajo aprobado o sin seña cobrada. Genera el cronograma.' })
  firmarBoleto(
    @Param('id', ParseUUIDPipe) id: string,
    @Body(ValidationPipe) dto: FirmarBoletoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.firmarBoleto(id, dto, user.empresa_id, user.id);
  }

  @Patch(':id/cuotas/:cuotaId')
  @UseGuards(PermissionGuard)
  @RequirePermission('INMOBILIARIO', 'INM_OPE_OPERACION_EDITAR')
  @ApiOperation({ summary: 'Fija el vencimiento de una cuota pendiente (ej. la de posesión)' })
  actualizarCuota(
    @Param('id', ParseUUIDPipe) id: string,
    @Param('cuotaId', ParseUUIDPipe) cuotaId: string,
    @Body(ValidationPipe) dto: ActualizarCuotaDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.actualizarCuota(id, cuotaId, dto, user.empresa_id, user.id);
  }
}
