import {
    Body,
    Controller,
    Delete,
    Get,
    HttpException,
    HttpStatus,
    Param,
    Post,
    Put,
    Query,
    UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiParam, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger';
import { RequireModule } from 'src/auth/decorators/require-module.decorator';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { ModuleGuard } from 'src/auth/guards/module.guard';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import { ActualizarPlanCuotasDto } from './dto/actualizar-plan-cuotas.dto';
import { CalcularCuotasDto } from './dto/calcular-cuotas.dto';
import { CrearPlanCuotasDto } from './dto/crear-plan-cuotas.dto';
import { ActualizarCuotaIndividualDto, CrearCuotaIndividualDto } from './dto/cuota-individual.dto';
import { ObtenerPlanesAplicablesDto } from './dto/obtener-planes-aplicables.dto';
import { PlanesCuotasService } from './planes-cuotas.service';

@ApiTags('Planes de Cuotas')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('VENTAS')
@RequirePermission('VENTAS', 'VEN_PCA_PLAN_VER')
@Controller({ path: 'planes-cuotas', version: '1' })
export class PlanesCuotasController {
  constructor(private readonly planesCuotasService: PlanesCuotasService) {}

  @Post()
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_CREAR')
  @ApiOperation({ summary: 'Crear nuevo plan de cuotas' })
  @ApiResponse({
    status: 201,
    description: 'Plan de cuotas creado exitosamente',
  })
  @ApiResponse({ status: 400, description: 'Datos inválidos o plan ya existe' })
  async crearPlan(@Body() dto: CrearPlanCuotasDto, @GetUser() user: LoginUserInfo) {
    try {
      dto.empresaId = user.empresa_id;
      const plan = await this.planesCuotasService.crearPlan(dto, user.username);
      return {
        success: true,
        message: 'Plan de cuotas creado exitosamente',
        data: plan,
      };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al crear el plan de cuotas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('empresa')
  @ApiOperation({
    summary: 'Obtener planes de cuotas de la empresa del usuario',
  })
  @ApiQuery({
    name: 'activo',
    required: false,
    type: Boolean,
    description: 'Filtrar por estado activo',
  })
  @ApiResponse({ status: 200, description: 'Lista de planes de cuotas' })
  async obtenerPlanes(@GetUser() user: LoginUserInfo, @Query('activo') activo?: string) {
    try {
      const activoBoolean = activo !== undefined ? activo === 'true' : undefined;
      const planes = await this.planesCuotasService.obtenerPlanes(user.empresa_id, activoBoolean);
      return { success: true, data: planes };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al obtener los planes de cuotas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Post('aplicables')
  @ApiOperation({
    summary: 'Planes de cuotas automáticos aplicables al carrito actual (filtrados por categoría/precio, Fase 7)',
  })
  @ApiResponse({ status: 201, description: 'Lista de planes aplicables' })
  async obtenerPlanesAplicables(@GetUser() user: LoginUserInfo, @Body() dto: ObtenerPlanesAplicablesDto) {
    try {
      const planes = await this.planesCuotasService.obtenerPlanesAplicables(
        user.empresa_id,
        dto.items,
        dto.montoTotal,
      );
      return { success: true, data: planes };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al obtener los planes aplicables',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  // ===== CUOTAS INDIVIDUALES POR PRODUCTO =====
  // Estas rutas deben ir ANTES de @Get(':id') para evitar que NestJS
  // interprete "individuales" como un :id de plan.

  @Post('individuales')
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_EDITAR')
  @ApiOperation({ summary: 'Crear cuota individual para un producto' })
  @ApiResponse({
    status: 201,
    description: 'Cuota individual creada exitosamente',
  })
  @ApiResponse({
    status: 400,
    description: 'Datos inválidos o cuota ya existe',
  })
  async crearCuotaIndividual(@Body() dto: CrearCuotaIndividualDto, @GetUser() user: LoginUserInfo) {
    try {
      const cuota = await this.planesCuotasService.crearCuotaIndividual(dto, user.empresa_id, user.username);
      return {
        success: true,
        message: 'Cuota individual creada exitosamente',
        data: cuota,
      };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al crear la cuota individual',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('individuales/producto/:productoId')
  @ApiOperation({ summary: 'Obtener cuotas individuales de un producto' })
  @ApiParam({ name: 'productoId', description: 'ID del producto' })
  @ApiResponse({
    status: 200,
    description: 'Lista de cuotas individuales del producto',
  })
  async obtenerCuotasProducto(@Param('productoId') productoId: string, @GetUser() user: LoginUserInfo) {
    try {
      const cuotas = await this.planesCuotasService.obtenerCuotasProducto(productoId, user.empresa_id);
      return { success: true, data: cuotas };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al obtener las cuotas del producto',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Put('individuales/:id')
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_EDITAR')
  @ApiOperation({ summary: 'Actualizar cuota individual' })
  @ApiParam({ name: 'id', description: 'ID de la cuota individual' })
  @ApiResponse({ status: 200, description: 'Cuota individual actualizada' })
  @ApiResponse({ status: 404, description: 'Cuota individual no encontrada' })
  async actualizarCuotaIndividual(
    @Param('id') id: string,
    @Body() dto: ActualizarCuotaIndividualDto,
    @GetUser() user: LoginUserInfo,
  ) {
    try {
      const cuota = await this.planesCuotasService.actualizarCuotaIndividual(id, user.empresa_id, dto, user.username);
      return {
        success: true,
        message: 'Cuota individual actualizada exitosamente',
        data: cuota,
      };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al actualizar la cuota individual',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Delete('individuales/:id')
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_EDITAR')
  @ApiOperation({ summary: 'Eliminar cuota individual' })
  @ApiParam({ name: 'id', description: 'ID de la cuota individual' })
  @ApiResponse({ status: 200, description: 'Cuota individual eliminada' })
  @ApiResponse({ status: 404, description: 'Cuota individual no encontrada' })
  async eliminarCuotaIndividual(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    try {
      const result = await this.planesCuotasService.eliminarCuotaIndividual(id, user.empresa_id, user.id);
      return { success: true, ...result };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al eliminar la cuota individual',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  // ===== PLANES DE CUOTAS (rutas con :id) =====

  @Get(':id')
  @ApiOperation({ summary: 'Obtener plan de cuotas por ID' })
  @ApiParam({ name: 'id', description: 'ID del plan de cuotas' })
  @ApiResponse({ status: 200, description: 'Plan de cuotas encontrado' })
  @ApiResponse({ status: 404, description: 'Plan de cuotas no encontrado' })
  async obtenerPlanPorId(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    try {
      const plan = await this.planesCuotasService.obtenerPlanPorId(id, user.empresa_id);
      return { success: true, data: plan };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al obtener el plan de cuotas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Put(':id')
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_EDITAR')
  @ApiOperation({ summary: 'Actualizar plan de cuotas' })
  @ApiParam({ name: 'id', description: 'ID del plan de cuotas' })
  @ApiResponse({
    status: 200,
    description: 'Plan de cuotas actualizado exitosamente',
  })
  @ApiResponse({ status: 404, description: 'Plan de cuotas no encontrado' })
  async actualizarPlan(@Param('id') id: string, @Body() dto: ActualizarPlanCuotasDto, @GetUser() user: LoginUserInfo) {
    try {
      const plan = await this.planesCuotasService.actualizarPlan(id, user.empresa_id, dto, user.username);
      return {
        success: true,
        message: 'Plan de cuotas actualizado exitosamente',
        data: plan,
      };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al actualizar el plan de cuotas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Delete(':id')
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_ELIMINAR')
  @ApiOperation({ summary: 'Eliminar plan de cuotas' })
  @ApiParam({ name: 'id', description: 'ID del plan de cuotas' })
  @ApiResponse({
    status: 200,
    description: 'Plan de cuotas eliminado exitosamente',
  })
  @ApiResponse({ status: 404, description: 'Plan de cuotas no encontrado' })
  @ApiResponse({
    status: 400,
    description: 'No se puede eliminar el plan (tiene cuotas asociadas)',
  })
  async eliminarPlan(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    try {
      await this.planesCuotasService.eliminarPlan(id, user.empresa_id, user.id);
      return {
        success: true,
        message: 'Plan de cuotas eliminado exitosamente',
      };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al eliminar el plan de cuotas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Post('calcular')
  @RequirePermission('VENTAS', 'VEN_PCA_PLAN_USAR')
  @ApiOperation({
    summary: 'Calcular cuotas según un plan (simulación o aplicación)',
  })
  @ApiResponse({ status: 201, description: 'Cuotas calculadas exitosamente' })
  @ApiResponse({ status: 400, description: 'Datos inválidos o plan no válido' })
  @ApiResponse({ status: 404, description: 'Plan de cuotas no encontrado' })
  async calcularCuotas(@Body() dto: CalcularCuotasDto, @GetUser() user: LoginUserInfo) {
    try {
      const resultado = await this.planesCuotasService.calcularCuotas(dto, user.username);
      return { success: true, data: resultado };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al calcular las cuotas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('cuotas-calculadas/empresa')
  @ApiOperation({ summary: 'Obtener cuotas calculadas de la empresa' })
  @ApiQuery({
    name: 'clienteId',
    required: false,
    description: 'Filtrar por cliente',
  })
  @ApiQuery({
    name: 'estado',
    required: false,
    description: 'Filtrar por estado',
  })
  @ApiResponse({ status: 200, description: 'Lista de cuotas calculadas' })
  async obtenerCuotasCalculadas(
    @GetUser() user: LoginUserInfo,
    @Query('clienteId') clienteId?: string,
    @Query('estado') estado?: string,
  ) {
    try {
      const cuotas = await this.planesCuotasService.obtenerCuotasCalculadas(user.empresa_id, clienteId, estado);
      return { success: true, data: cuotas };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al obtener las cuotas calculadas',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('cuotas-calculadas/:id')
  @ApiOperation({ summary: 'Obtener cuota calculada por ID' })
  @ApiParam({ name: 'id', description: 'ID de la cuota calculada' })
  @ApiResponse({ status: 200, description: 'Cuota calculada encontrada' })
  @ApiResponse({ status: 404, description: 'Cuota calculada no encontrada' })
  async obtenerCuotaCalculadaPorId(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    try {
      const cuota = await this.planesCuotasService.obtenerCuotaCalculadaPorId(id, user.empresa_id);
      return { success: true, data: cuota };
    } catch (error) {
      if (error instanceof HttpException) throw error;
      throw new HttpException(
        {
          success: false,
          message: error.message || 'Error al obtener la cuota calculada',
        },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
