import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Put,
  Query,
  UseGuards,
  UseInterceptors,
} from "@nestjs/common";
import {
  ApiBearerAuth,
  ApiOperation,
  ApiQuery,
  ApiResponse,
  ApiTags,
} from "@nestjs/swagger";
import { RequirePermission } from "../auth/decorators/require-permission.decorator";
import { JwtAuthGuard } from "../auth/guards/jwt-auth.guard";
import { PermissionGuard } from "../auth/guards/permission.guard";
import { TenantGuard } from "../tenancy/tenant.guard";
import { TenantReleaseInterceptor } from "../tenancy/tenant-release.interceptor";
import { CreateProductoDto } from "./dto/create-producto.dto";
import { UpdateProductoDto } from "./dto/update-producto.dto";
import { ProductosService } from "./productos.service";

/**
 * Parse a query-string boolean value.
 * HTTP query params are always strings ("true", "false", "1", "0").
 * Returns undefined when the param is absent so the service can skip the filter.
 */
function parseBooleanQuery(value: unknown): boolean | undefined {
  if (value === undefined || value === null || value === "") {
    return undefined;
  }

  const normalized = String(value).trim().toLowerCase();
  if (normalized === "true" || normalized === "1") {
    return true;
  }
  if (normalized === "false" || normalized === "0") {
    return false;
  }

  return undefined;
}

@ApiTags("productos")
@ApiBearerAuth()
@UseGuards(JwtAuthGuard, TenantGuard, PermissionGuard)
@UseInterceptors(TenantReleaseInterceptor)
@RequirePermission("productos", "read")
@Controller("productos")
export class ProductosController {
  constructor(private readonly productosService: ProductosService) {}

  @Get("search")
  @ApiOperation({ summary: "Buscar productos/servicios" })
  @ApiQuery({ name: "q", required: true, description: "Termino de busqueda" })
  @ApiQuery({ name: "limit", required: false })
  @ApiQuery({ name: "esServicio", required: false, type: Boolean })
  @ApiQuery({ name: "soloTaller", required: false, type: Boolean })
  async search(
    @Query("q") q: string,
    @Query("limit") limit?: number,
    @Query("esServicio") esServicioRaw?: string,
    @Query("soloTaller") soloTallerRaw?: string,
  ) {
    return this.productosService.search(
      q,
      limit,
      parseBooleanQuery(esServicioRaw),
      parseBooleanQuery(soloTallerRaw),
    );
  }

  @Get("top")
  @ApiOperation({
    summary: "Obtener productos mas usados (para cache offline)",
  })
  @ApiQuery({ name: "limit", required: false })
  @ApiQuery({ name: "esServicio", required: false, type: Boolean })
  @ApiQuery({ name: "soloTaller", required: false, type: Boolean })
  async findTop(
    @Query("limit") limit?: number,
    @Query("esServicio") esServicioRaw?: string,
    @Query("soloTaller") soloTallerRaw?: string,
  ) {
    return this.productosService.findTopProductos(
      limit,
      parseBooleanQuery(esServicioRaw),
      parseBooleanQuery(soloTallerRaw),
    );
  }

  @Get(":plu")
  @ApiOperation({ summary: "Obtener producto por PLU" })
  async findByPlu(@Param("plu") plu: string) {
    return this.productosService.findByPlu(plu);
  }

  @Post()
  @RequirePermission("productos", "write")
  @ApiOperation({ summary: "Crear producto local" })
  @ApiResponse({ status: 201, description: "Producto creado" })
  async create(@Body() dto: CreateProductoDto) {
    return this.productosService.create(dto);
  }

  @Put(":plu")
  @RequirePermission("productos", "write")
  @ApiOperation({ summary: "Actualizar producto local" })
  @ApiResponse({ status: 200, description: "Producto actualizado" })
  async update(@Param("plu") plu: string, @Body() dto: UpdateProductoDto) {
    return this.productosService.update(plu, dto);
  }

  @Delete(":plu")
  @RequirePermission("productos", "write")
  @ApiOperation({ summary: "Eliminar producto local" })
  @ApiResponse({ status: 200, description: "Producto eliminado" })
  async delete(@Param("plu") plu: string) {
    return this.productosService.delete(plu);
  }
}
