import { Body, Controller, Get, Param, Post, Query, UseGuards, BadRequestException } from '@nestjs/common';
import { ApiOperation, ApiQuery, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { AppTokenGuard } from 'src/app-token.guard';
import { StorePublicService } from './store-public.service';

/** Tope del catálogo que se manda entero a la tienda. */
export const STORE_CATALOG_MAX = 5000;

@ApiTags('Store Público')
@ApiSecurity('x-app-key')
@UseGuards(AppTokenGuard)
@Controller({ path: 'store', version: '1' })
export class StorePublicController {
  constructor(private readonly service: StorePublicService) {}

  @Get('productos/search')
  @ApiOperation({ summary: 'Búsqueda inteligente de productos por nombre, código, marca o categoría' })
  @ApiQuery({ name: 'q', description: 'Término de búsqueda' })
  @ApiQuery({ name: 'subdominio', description: 'Subdominio de la tienda (ej: empresa1)' })
  @ApiQuery({ name: 'limit', required: false, description: 'Máx. resultados (default 8, max 500)' })
  @ApiQuery({ name: 'page', required: false, description: 'Página de resultados (default 1)' })
  async search(
    @Query('q') q: string,
    @Query('subdominio') subdominio: string,
    @Query('limit') limit?: string,
    @Query('page') page?: string,
  ) {
    if (!q || q.trim().length < 3 || !subdominio) {
      return {
        query: q?.trim() ?? '',
        normalizedQuery: '',
        suggestedQuery: null,
        matchType: 'none',
        results: [],
        alternatives: [],
        total: 0,
        unavailableProductName: null,
      };
    }
    const parsedLimit = Number(limit ?? '8');
    const parsedPage = Number(page ?? '1');
    const n = Math.min(Math.max(Number.isFinite(parsedLimit) ? Math.floor(parsedLimit) : 8, 1), 500);
    const currentPage = Math.max(Number.isFinite(parsedPage) ? Math.floor(parsedPage) : 1, 1);
    return this.service.searchProductos(subdominio, q, n, currentPage);
  }

  @Get('bootstrap')
  @ApiOperation({ summary: 'Carga inicial del catálogo: productos, categorías y destacadas' })
  @ApiQuery({ name: 'subdominio', description: 'Subdominio de la tienda' })
  @ApiQuery({ name: 'limit', required: false, description: 'Máx. productos (default 300, max 5000)' })
  async bootstrap(@Query('subdominio') subdominio: string, @Query('limit') limit?: string) {
    if (!subdominio) {
      return { products: [], categories: ['Todos'], featuredCategories: [] };
    }
    // La tienda filtra y pagina el catálogo en el navegador: lo que no viene acá no
    // aparece en ninguna categoría (sólo en el buscador). Con tope 500, Comercial Kety
    // mostraba 500 de 1.690 productos publicados. 1.690 pesan ~740 KB (≈170 KB gzip).
    const n = Math.min(Number(limit ?? '300') || 300, STORE_CATALOG_MAX);
    return this.service.getBootstrap(subdominio, n);
  }

  @Get('productos/:id')
  @ApiOperation({ summary: 'Ficha pública de producto con galería y especificaciones' })
  @ApiQuery({ name: 'subdominio', description: 'Subdominio de la tienda' })
  async detalle(@Param('id') id: string, @Query('subdominio') subdominio: string) {
    return this.service.getProductoDetalle(subdominio, id);
  }

  @Post('cart/validate')
  @ApiOperation({ summary: 'Valida el carrito: recalcula precios y verifica stock reales (base del checkout)' })
  async validateCart(
    @Body() body: { subdominio: string; items: { id: string; quantity: number }[] },
  ) {
    if (!body?.subdominio || !Array.isArray(body.items)) {
      return { valid: false, lines: [], subtotal: 0, issues: ['Solicitud inválida.'] };
    }
    return this.service.validateCart(body.subdominio, body.items);
  }

  @Post('checkout')
  @ApiOperation({ summary: 'Crear pedido (flujo manual): valida carrito y registra la sesión de checkout' })
  async checkout(
    @Body()
    body: {
      subdominio: string;
      customer: { name?: string; email?: string; phone?: string; document?: string; ruc?: string; dv?: string; razonSocial?: string; naturaleza?: number; tipoContribuyente?: number; consultadoSIFEN?: boolean; sifenNoVerificado?: boolean };
      delivery: { methodId?: string; type?: 'delivery' | 'pickup'; address?: string; departamento?: string; distrito?: string; ciudad?: string; nroCasa?: string; lat?: number; lng?: number };
      items: { id: string; quantity: number }[];
      paymentMethodId?: string;
      financing?: { productoId: string; planId: string }[];
      callbackBase?: string;
      comentarios?: string;
    },
  ) {
    if (!body?.subdominio || !Array.isArray(body.items) || body.items.length === 0) {
      return { ok: false, issues: ['Solicitud inválida o carrito vacío.'] };
    }
    return this.service.createCheckout({
      subdominio: body.subdominio,
      customer: body.customer ?? {},
      delivery: body.delivery ?? {},
      items: body.items,
      paymentMethodId: body.paymentMethodId,
      financing: Array.isArray(body.financing) ? body.financing : [],
      callbackBase: body.callbackBase,
      // Texto libre del comprador: se recorta para que un cliente no pueda mandar
      // un campo arbitrariamente grande a una columna sin límite.
      comentarios:
        typeof body.comentarios === 'string' ? body.comentarios.trim().slice(0, 1000) : undefined,
    });
  }

  @Get('checkout/:token')
  @ApiOperation({ summary: 'Estado público de un pedido por token' })
  @ApiQuery({ name: 'subdominio', description: 'Subdominio de la tienda' })
  async checkoutStatus(@Param('token') token: string, @Query('subdominio') subdominio: string) {
    return this.service.getCheckoutStatus(subdominio, token);
  }

  @Get('ruc/:ruc')
  @ApiOperation({ summary: 'Consulta datos de RUC via SIFEN (tipOpe: 7)' })
  @ApiQuery({ name: 'subdominio', description: 'Subdominio de la tienda (para resolver usuario_funcional SIFEN)' })
  async consultarRuc(@Param('ruc') ruc: string, @Query('subdominio') subdominio: string) {
    if (!ruc || !/^\d{6,8}$/.test(ruc)) {
      throw new BadRequestException('RUC debe ser numérico de 6 a 8 dígitos');
    }
    return this.service.consultarRuc(subdominio, ruc);
  }
}
