// PÚBLICO — sin autenticación JWT. Acceso por token de presupuesto.
import { Body, Controller, Get, HttpCode, HttpStatus, Param, Post, Req, Res } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import type { Request, Response } from 'express';
import { RejectPublicoDto } from './dto/reject-publico.dto';
import { PresupuestosPublicoService } from './presupuestos-publico.service';

/** Pixel GIF transparente 1x1 para el tracking de apertura de email. */
const PIXEL_GIF = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64');

@ApiTags('Presupuestos (público)')
@Controller({ path: 'pub/presupuesto', version: '1' })
export class PresupuestoPublicoController {
  constructor(private readonly publicoService: PresupuestosPublicoService) {}

  @Get('track/open/:token')
  @ApiOperation({ summary: 'Pixel de tracking de apertura del email (marca VIEWED)' })
  async trackOpen(@Param('token') token: string, @Res() res: Response) {
    await this.publicoService.trackOpen(token).catch(() => undefined);
    res.set({
      'Content-Type': 'image/gif',
      'Content-Length': String(PIXEL_GIF.length),
      'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
      Pragma: 'no-cache',
      Expires: '0',
    });
    res.end(PIXEL_GIF);
  }

  @Get(':token')
  @ApiOperation({ summary: 'Datos del presupuesto para el portal del cliente' })
  getPublic(@Param('token') token: string) {
    return this.publicoService.getPublic(token);
  }

  @Get(':token/pdf')
  @ApiOperation({ summary: 'Descargar el PDF del presupuesto desde el portal' })
  async pdf(@Param('token') token: string, @Res() res: Response) {
    const { buffer, numero } = await this.publicoService.getPublicPdf(token);
    res.set({
      'Content-Type': 'application/pdf',
      'Content-Disposition': `inline; filename="presupuesto-${numero}.pdf"`,
      'Content-Length': String(buffer.length),
    });
    res.send(buffer);
  }

  @Post(':token/accept')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'El cliente acepta el presupuesto' })
  accept(@Param('token') token: string, @Req() req: Request) {
    return this.publicoService.accept(token, this.meta(req));
  }

  @Post(':token/reject')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'El cliente rechaza el presupuesto' })
  reject(@Param('token') token: string, @Body() dto: RejectPublicoDto, @Req() req: Request) {
    return this.publicoService.reject(token, dto.motivo, this.meta(req));
  }

  private meta(req: Request): { ip?: string; userAgent?: string } {
    const fwd = req.headers['x-forwarded-for'];
    const ip = (Array.isArray(fwd) ? fwd[0] : fwd?.split(',')[0]) || req.ip;
    return { ip: ip ?? undefined, userAgent: req.headers['user-agent'] };
  }
}
