import { Body, Controller, Get, Param, Patch, Post, Query, UseGuards, ValidationPipe } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiBody, ApiParam, ApiQuery } from '@nestjs/swagger';
import { RequireModule } from 'src/auth/decorators/require-module.decorator';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import { ModuleGuard } from 'src/auth/guards/module.guard';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import type { LoginUserInfo } from '../auth/dto/login.dto';
import { GetUser } from '../auth/get-user.decorator';
import { AjustarStockDto, CreateStockDto, ReservarStockDto, TransferirStockDto } from './dto/create-stock.dto';
import { StockService } from './stock.service';

@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), ModuleGuard)
@RequireModule('INVENTARIO')
@Controller({ version: '1', path: 'stock' })
export class StockController {
  constructor(private readonly stockService: StockService) {}

  @Get('deposito/:deposito_id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_VER')
  @ApiParam({ name: 'deposito_id', description: 'ID del depósito' })
  async findByDeposito(@Param('deposito_id') deposito_id: string, @GetUser() user: LoginUserInfo) {
    return this.stockService.findByDeposito(deposito_id, user.empresa_id);
  }

  @Get('producto/:producto_id')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_VER')
  @ApiParam({ name: 'producto_id', description: 'ID del producto' })
  async findByProducto(@Param('producto_id') producto_id: string, @GetUser() user: LoginUserInfo) {
    return this.stockService.findByProducto(producto_id, user.empresa_id);
  }

  @Get('consulta')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_VER')
  @ApiQuery({ name: 'deposito_id', description: 'ID del depósito' })
  @ApiQuery({ name: 'producto_id', description: 'ID del producto' })
  async findOne(
    @Query('deposito_id') deposito_id: string,
    @Query('producto_id') producto_id: string,
    @GetUser() user: LoginUserInfo,
  ) {
    return this.stockService.findOne(deposito_id, producto_id, user.empresa_id);
  }

  @Post()
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_AJUSTAR')
  @ApiBody({ type: CreateStockDto })
  async upsertStock(@Body(ValidationPipe) dto: CreateStockDto, @GetUser() user: LoginUserInfo) {
    return this.stockService.upsertStock(dto, user?.id, user?.empresa_id);
  }

  @Post('ajustar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_AJUSTAR')
  @ApiBody({ type: AjustarStockDto })
  async ajustarStock(@Body(ValidationPipe) dto: AjustarStockDto, @GetUser() user: LoginUserInfo) {
    const tipo_codigo = dto.cantidad >= 0 ? 'ENTRADA' : 'SALIDA';
    return this.stockService.ajustarStock(dto, user.id, tipo_codigo, user?.empresa_id);
  }

  @Post('reservar')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_AJUSTAR')
  @ApiBody({ type: ReservarStockDto })
  async reservarStock(@Body(ValidationPipe) dto: ReservarStockDto, @GetUser() user: LoginUserInfo) {
    return this.stockService.reservarStock(dto, user?.id, user?.empresa_id);
  }

  @Post('liberar-reserva')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_AJUSTAR')
  @ApiBody({ type: ReservarStockDto })
  async liberarReserva(@Body(ValidationPipe) dto: ReservarStockDto, @GetUser() user: LoginUserInfo) {
    return this.stockService.liberarReserva(dto, user?.id, user?.empresa_id);
  }

  @Post('transferir')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_AJUSTAR')
  @ApiBody({ type: TransferirStockDto })
  async transferirStock(@Body(ValidationPipe) dto: TransferirStockDto, @GetUser() user: LoginUserInfo) {
    // TODO: Obtener tipo_movimiento_id para transferencias
    const tipo_movimiento_id = 'TRANSFERENCIA';
    return this.stockService.transferirStock(dto, user.id, tipo_movimiento_id, user?.empresa_id);
  }

  @Patch(':id/limites')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_AJUSTAR')
  @ApiParam({ name: 'id', description: 'ID del registro stock_deposito' })
  async updateLimites(
    @Param('id') id: string,
    @Body() body: { stock_minimo?: number; stock_maximo?: number; ubicacion?: string },
    @GetUser() user: LoginUserInfo,
  ) {
    return this.stockService.updateLimites(id, body, user.id, user.empresa_id);
  }

  @Get('reporte/niveles')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_VER')
  @ApiQuery({ name: 'page', required: false })
  @ApiQuery({ name: 'limit', required: false })
  @ApiQuery({ name: 'deposito_id', required: false })
  @ApiQuery({ name: 'sucursal_id', required: false })
  @ApiQuery({ name: 'estado', required: false })
  @ApiQuery({ name: 'search', required: false })
  async getReporteNiveles(
    @GetUser() user: LoginUserInfo,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('deposito_id') deposito_id?: string,
    @Query('sucursal_id') sucursal_id?: string,
    @Query('estado') estado?: string,
    @Query('search') search?: string,
  ) {
    return this.stockService.getReporteNiveles(user.empresa_id, {
      page: page ? Number(page) : 1,
      limit: limit ? Number(limit) : 25,
      deposito_id,
      sucursal_id,
      estado,
      search,
      usuarioId: user.id,
    });
  }

  @Get('bajo-minimo')
  @UseGuards(PermissionGuard)
  @RequirePermission('INVENTARIO', 'INV_STK_STOCK_VER')
  async getStockBajoMinimo(@GetUser() user: LoginUserInfo) {
    return this.stockService.getStockBajoMinimo(user.empresa_id, user.id);
  }
}
