import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Put,
  Query,
  Res,
  UseGuards,
  UseInterceptors,
  ValidationPipe,
} from '@nestjs/common';
import { AuditInterceptor } from '../audit/audit.interceptor';
import { Auditable } from '../audit/auditable.decorator';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiBody, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger';
import type { LoginUserInfo } from '../auth/dto/login.dto';
import { GetUser } from '../auth/get-user.decorator';
import { RequireModule, RequirePermission } from '../auth/decorators';
import { ModuleGuard } from '../auth/guards/module.guard';
import { PermissionGuard } from '../auth/guards/permission.guard';
import { CreateSolicitudCreditoDto, CreateSolicitudCreditoItemDto } from './dto/create-solicitud-credito.dto';
import { QuerySolicitudesCreditoDto } from './dto/query-solicitudes-credito.dto';
import { UpdateSolicitudCreditoDto } from './dto/update-solicitud-credito.dto';
import { SolicitudesCreditoService } from './solicitudes-credito.service';

@ApiTags('Solicitudes de Crédito')
@ApiBearerAuth()
@Controller({ version: '1', path: 'solicitudes-credito' })
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('VENTAS')
export class SolicitudesCreditoController {
  constructor(private readonly service: SolicitudesCreditoService) {}

  // ═══════════ CRUD ═══════════

  @Post()
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_CREAR')
  @Auditable('solicitud_credito')
  @UseInterceptors(AuditInterceptor)
  @ApiBody({ type: CreateSolicitudCreditoDto })
  async create(@Body(ValidationPipe) dto: CreateSolicitudCreditoDto, @GetUser() user: LoginUserInfo) {
    return this.service.create(dto, user.empresa_id, user.id);
  }

  @Get()
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_VER')
  async findAll(@Query() query: QuerySolicitudesCreditoDto, @GetUser() user: LoginUserInfo) {
    return this.service.findAll(query, user.empresa_id);
  }

  @Get('aprobadas')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_VER')
  @ApiQuery({ name: 'sucursal_id', required: false })
  @ApiQuery({ name: 'cliente_id', required: false })
  async findAprobadas(
    @GetUser() user: LoginUserInfo,
    @Query('sucursal_id') sucursal_id?: string,
    @Query('cliente_id') cliente_id?: string,
  ) {
    return this.service.findAprobadas(user.empresa_id, cliente_id, sucursal_id);
  }

  @Get(':id')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_VER')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async findOne(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.findOne(id, user.empresa_id);
  }

  @Put(':id')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_EDITAR')
  @Auditable('solicitud_credito')
  @UseInterceptors(AuditInterceptor)
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  @ApiBody({ type: UpdateSolicitudCreditoDto })
  async update(
    @Param('id') id: string,
    @Body(ValidationPipe) dto: UpdateSolicitudCreditoDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.update(id, dto, user.empresa_id, user.id);
  }

  @Delete(':id')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_ELIMINAR')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async remove(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.remove(id, user.empresa_id, user.id);
  }

  // ═══════════ ITEMS ═══════════

  @Post(':id/items')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_EDITAR')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  @ApiBody({ type: CreateSolicitudCreditoItemDto })
  async addItem(
    @Param('id') id: string,
    @Body(ValidationPipe) dto: CreateSolicitudCreditoItemDto,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.addItem(id, dto, user.empresa_id, user.id);
  }

  @Put(':id/items/:itemId')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_EDITAR')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  @ApiParam({ name: 'itemId', description: 'ID del item' })
  async updateItem(
    @Param('id') id: string,
    @Param('itemId') itemId: string,
    @Body(ValidationPipe) dto: Partial<CreateSolicitudCreditoItemDto>,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.updateItem(id, itemId, dto, user.empresa_id, user.id);
  }

  @Delete(':id/items/:itemId')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_EDITAR')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  @ApiParam({ name: 'itemId', description: 'ID del item' })
  async removeItem(
    @Param('id') id: string,
    @Param('itemId') itemId: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.removeItem(id, itemId, user.empresa_id, user.id);
  }

  // ═══════════ FLUJO DE ESTADOS ═══════════

  @Patch(':id/enviar-aprobacion')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_EDITAR')
  @Auditable('solicitud_credito')
  @UseInterceptors(AuditInterceptor)
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async enviarAprobacion(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.enviarAprobacion(id, user.empresa_id, user.id);
  }

  @Patch(':id/aprobar')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_APROBAR')
  @Auditable('solicitud_credito')
  @UseInterceptors(AuditInterceptor)
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async aprobar(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.aprobar(id, user.empresa_id, user.id);
  }

  @Patch(':id/rechazar')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_APROBAR')
  @Auditable('solicitud_credito')
  @UseInterceptors(AuditInterceptor)
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async rechazar(
    @Param('id') id: string,
    @Body('motivo_rechazo') motivo: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.rechazar(id, motivo, user.empresa_id, user.id);
  }

  @Patch(':id/cancelar')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_ELIMINAR')
  @Auditable('solicitud_credito')
  @UseInterceptors(AuditInterceptor)
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async cancelar(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.cancelar(id, user.empresa_id, user.id);
  }

  @Patch(':id/facturada')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_EDITAR')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async marcarFacturada(
    @Param('id') id: string,
    @Body('factura_id') facturaId: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.service.marcarFacturada(id, facturaId, user.empresa_id, user.id);
  }

  // ═══════════ HISTORIAL ═══════════

  @Get(':id/historial')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_VER')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  async getHistorial(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.service.getHistorial(id, user.empresa_id);
  }

  // ═══════════ PDF ═══════════

  @Get(':id/pdf')
  @RequirePermission('VENTAS', 'VEN_SOL_SOLICITUD_VER')
  @ApiParam({ name: 'id', description: 'ID de la solicitud' })
  @ApiQuery({ name: 'tipo', required: false, description: 'view | base64' })
  async generatePdf(
    @Param('id') id: string,
    @Query('tipo') tipo: string,
    @GetUser() user: LoginUserInfo,
    @Res() res: any,
  ) {
    const tipoRetorno = tipo || 'view';
    const result = await this.service.generatePdf(id, user.empresa_id, tipoRetorno);

    if (tipoRetorno === 'base64') {
      return res.json(result);
    }

    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', `inline; filename="solicitud-credito-${id}.pdf"`);
    return res.send(result.pdfBuffer);
  }
}
