import {
  Body,
  Controller,
  Get,
  Param,
  Patch,
  Post,
  Put,
  Query,
  UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
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 { PermissionGuard } from 'src/auth/guards/permission.guard';
import { CreateRequisicionDto } from './dto/create-requisicion.dto';
import {
  AprobarRequisicionDto,
  CancelarRequisicionDto,
  GenerarDesdeRequisicionGastoDto,
  GenerarDesdeRequisicionOrdenCompraDto,
  GenerarOrdenesCompraDistribuidasDto,
  RechazarRequisicionDto,
  UpsertRequisicionAprobacionConfigDto,
  UpsertRequisicionPresupuestoDto,
} from './dto/requisicion-config.dto';
import { UpdateRequisicionDto } from './dto/update-requisicion.dto';
import { RequisicionesService } from './requisiciones.service';

@ApiTags('Requisiciones')
@Controller({ path: 'requisiciones', version: '1' })
export class RequisicionesController {
  constructor(private readonly requisicionesService: RequisicionesService) {}

  @Post()
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Crear requisición (compra o gasto)' })
  create(@Body() dto: CreateRequisicionDto, @GetUser() user: LoginUserInfo) {
    return this.requisicionesService.create(dto, user.empresa_id, user.id);
  }

  @Get()
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Listar requisiciones' })
  @ApiQuery({ name: 'page', required: false })
  @ApiQuery({ name: 'limit', required: false })
  @ApiQuery({ name: 'origen_tipo', required: false })
  @ApiQuery({ name: 'estado', required: false })
  @ApiQuery({ name: 'fecha_desde', required: false })
  @ApiQuery({ name: 'fecha_hasta', required: false })
  @ApiQuery({ name: 'search', required: false })
  findAll(
    @GetUser() user: LoginUserInfo,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('origen_tipo') origen_tipo?: string,
    @Query('estado') estado?: string,
    @Query('fecha_desde') fecha_desde?: string,
    @Query('fecha_hasta') fecha_hasta?: string,
    @Query('search') search?: string,
  ) {
    return this.requisicionesService.findAll(user.empresa_id, user.id, {
      page,
      limit,
      origen_tipo,
      estado,
      fecha_desde,
      fecha_hasta,
      search,
    });
  }

  @Get('aprobaciones-config')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Configuración de niveles de aprobación por monto y rol' })
  getAprobacionesConfig(@GetUser() user: LoginUserInfo) {
    return this.requisicionesService.getAprobacionesConfig(user.empresa_id);
  }

  @Put('aprobaciones-config')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Actualizar configuración de aprobación de requisiciones' })
  putAprobacionesConfig(
    @GetUser() user: LoginUserInfo,
    @Body() dto: UpsertRequisicionAprobacionConfigDto,
  ) {
    return this.requisicionesService.upsertAprobacionesConfig(user.empresa_id, dto);
  }

  @Get('presupuestos')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Listar presupuestos de requisiciones (por período/CC)' })
  @ApiQuery({ name: 'periodo_id', required: false })
  @ApiQuery({ name: 'centro_costo_id', required: false })
  @ApiQuery({ name: 'origen_tipo', required: false })
  getPresupuestos(
    @GetUser() user: LoginUserInfo,
    @Query('periodo_id') periodo_id?: string,
    @Query('centro_costo_id') centro_costo_id?: string,
    @Query('origen_tipo') origen_tipo?: string,
  ) {
    return this.requisicionesService.getPresupuestos(user.empresa_id, {
      periodo_id,
      centro_costo_id,
      origen_tipo,
    });
  }

  @Put('presupuestos')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Actualizar presupuestos de requisiciones' })
  putPresupuestos(@GetUser() user: LoginUserInfo, @Body() dto: UpsertRequisicionPresupuestoDto) {
    return this.requisicionesService.upsertPresupuestos(user.empresa_id, dto);
  }

  @Get(':id')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Detalle de requisición' })
  findOne(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.requisicionesService.findOne(id, user.empresa_id, user.id);
  }

  @Patch(':id')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Editar requisición (solo borrador)' })
  update(@Param('id') id: string, @Body() dto: UpdateRequisicionDto, @GetUser() user: LoginUserInfo) {
    return this.requisicionesService.update(id, dto, user.empresa_id, user.id);
  }

  @Patch(':id/enviar-aprobacion')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Enviar requisición a aprobación' })
  enviarAprobacion(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    return this.requisicionesService.enviarAprobacion(id, user.empresa_id, user.id);
  }

  @Patch(':id/aprobar')
  @UseGuards(AuthGuard('jwt'), PermissionGuard)
  @RequirePermission('COMPRAS', 'EDITAR')
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Aprobar requisición en el nivel correspondiente' })
  aprobar(@Param('id') id: string, @GetUser() user: LoginUserInfo, @Body() dto: AprobarRequisicionDto) {
    return this.requisicionesService.aprobar(id, user.empresa_id, user.id, dto);
  }

  @Patch(':id/rechazar')
  @UseGuards(AuthGuard('jwt'), PermissionGuard)
  @RequirePermission('COMPRAS', 'EDITAR')
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Rechazar requisición' })
  rechazar(@Param('id') id: string, @GetUser() user: LoginUserInfo, @Body() dto: RechazarRequisicionDto) {
    return this.requisicionesService.rechazar(id, user.empresa_id, user.id, dto);
  }

  @Patch(':id/cancelar')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Cancelar requisición' })
  cancelar(@Param('id') id: string, @GetUser() user: LoginUserInfo, @Body() dto: CancelarRequisicionDto) {
    return this.requisicionesService.cancelar(id, user.empresa_id, user.id, dto);
  }

  @Post(':id/crear-orden-compra')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Generar OC desde requisición aprobada de compra' })
  crearOrdenCompra(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Body() dto: GenerarDesdeRequisicionOrdenCompraDto,
  ) {
    return this.requisicionesService.crearOrdenCompraDesdeRequisicion(id, user.empresa_id, dto, user.id);
  }

  @Post(':id/crear-gasto')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Generar gasto desde requisición aprobada de gasto' })
  crearGasto(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Body() dto: GenerarDesdeRequisicionGastoDto,
  ) {
    return this.requisicionesService.crearGastoDesdeRequisicion(id, user.empresa_id, dto, user.id);
  }

  @Post('aprobaciones-config/aplicar-recomendada')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({
    summary:
      'Crear (si faltan) los perfiles recomendados y aplicar 4 niveles default para compras y gastos',
  })
  aplicarConfigRecomendada(@GetUser() user: LoginUserInfo) {
    return this.requisicionesService.aplicarConfiguracionRecomendada(user.empresa_id);
  }

  @Post(':id/generar-ordenes-compra')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({
    summary:
      'Distribuir líneas de una requisición entre proveedores y generar una OC por proveedor',
  })
  generarOrdenesCompraDistribuidas(
    @Param('id') id: string,
    @GetUser() user: LoginUserInfo,
    @Body() dto: GenerarOrdenesCompraDistribuidasDto,
  ) {
    return this.requisicionesService.generarOrdenesCompraDistribuidas(id, user.empresa_id, dto, user.id);
  }
}
