import {
  Body,
  Controller,
  Delete,
  Get,
  NotFoundException,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import type { LoginUserInfo } from '../../auth/dto/login.dto';
import { RequireModule, RequirePermission } from '../../auth/decorators';
import { ModuleGuard } from '../../auth/guards/module.guard';
import { PermissionGuard } from '../../auth/guards/permission.guard';
import { GetUser } from '../../auth/get-user.decorator';
import { PrismaService } from '../../prisma/prisma.service';
import {
  ActualizarWebhookEndpointDto,
  CrearWebhookEndpointDto,
} from '../dto/webhook-endpoint.dto';
import { assertSafeWebhookUrl } from './webhook-url.util';

@ApiTags('Cartera Inteligente — Webhooks')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), ModuleGuard, PermissionGuard)
@RequireModule('COBRANZAS')
@Controller({ path: 'cartera/webhooks', version: '1' })
export class WebhookController {
  constructor(private readonly prisma: PrismaService) {}

  @Get('endpoints')
  @RequirePermission('COBRANZAS', 'COB_CART_VER')
  @ApiOperation({ summary: 'Listar endpoints de webhooks de la empresa' })
  async listar(@GetUser() user: LoginUserInfo) {
    const rows = await this.prisma.tenant_webhook_endpoints.findMany({
      where: { empresa_id: user.empresa_id },
      orderBy: { creado_en: 'desc' },
    });
    return rows.map((r) => ({
      id: r.id,
      evento: r.evento,
      url: r.url,
      activo: r.activo,
      tiene_secreto: !!r.secreto_hmac,
      creado_en: r.creado_en,
    }));
  }

  @Post('endpoints')
  @RequirePermission('COBRANZAS', 'COB_CART_CONFIGURAR')
  @ApiOperation({ summary: 'Crear un nuevo endpoint suscrito a un evento' })
  async crear(@Body() dto: CrearWebhookEndpointDto, @GetUser() user: LoginUserInfo) {
    assertSafeWebhookUrl(dto.url);
    return this.prisma.tenant_webhook_endpoints.create({
      data: {
        empresa_id: user.empresa_id,
        evento: dto.evento,
        url: dto.url,
        secreto_hmac: dto.secreto_hmac ?? null,
        activo: true,
      },
    });
  }

  @Patch('endpoints/:id')
  @RequirePermission('COBRANZAS', 'COB_CART_CONFIGURAR')
  @ApiOperation({ summary: 'Actualizar URL, secreto o activar/desactivar' })
  async actualizar(
    @Param('id') id: string,
    @Body() dto: ActualizarWebhookEndpointDto,
    @GetUser() user: LoginUserInfo,
  ) {
    const existing = await this.prisma.tenant_webhook_endpoints.findFirst({
      where: { id, empresa_id: user.empresa_id },
    });
    if (!existing) throw new NotFoundException('Endpoint no encontrado');
    if (dto.url) assertSafeWebhookUrl(dto.url);
    return this.prisma.tenant_webhook_endpoints.update({
      where: { id },
      data: {
        url: dto.url ?? undefined,
        activo: dto.activo ?? undefined,
        secreto_hmac: dto.secreto_hmac ?? undefined,
      },
    });
  }

  @Delete('endpoints/:id')
  @RequirePermission('COBRANZAS', 'COB_CART_CONFIGURAR')
  @ApiOperation({ summary: 'Eliminar endpoint y sus deliveries' })
  async eliminar(@Param('id') id: string, @GetUser() user: LoginUserInfo) {
    const existing = await this.prisma.tenant_webhook_endpoints.findFirst({
      where: { id, empresa_id: user.empresa_id },
    });
    if (!existing) throw new NotFoundException('Endpoint no encontrado');
    await this.prisma.tenant_webhook_endpoints.delete({ where: { id } });
    return { ok: true };
  }

  @Get('deliveries')
  @RequirePermission('COBRANZAS', 'COB_CART_VER')
  @ApiOperation({ summary: 'Listar últimos deliveries con estado' })
  async deliveries(
    @GetUser() user: LoginUserInfo,
    @Query('endpoint_id') endpointId?: string,
    @Query('limit') limit?: string,
  ) {
    const take = Math.min(Number(limit) || 100, 500);
    return this.prisma.webhook_deliveries.findMany({
      where: {
        empresa_id: user.empresa_id,
        ...(endpointId ? { endpoint_id: endpointId } : {}),
      },
      orderBy: { created_at: 'desc' },
      take,
      select: {
        id: true,
        endpoint_id: true,
        evento: true,
        estado: true,
        intentos: true,
        response_code: true,
        last_error: true,
        created_at: true,
        delivered_at: true,
      },
    });
  }
}
