import { Controller, Get, Query, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { RequirePermission } from 'src/auth/decorators/require-permission.decorator';
import { RequireSubmodulo } from 'src/auth/decorators/require-submodulo.decorator';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { PermissionGuard } from 'src/auth/guards/permission.guard';
import { SubmoduloGuard } from 'src/auth/guards/submodulo.guard';
import { PrismaService } from 'src/prisma/prisma.service';
import { OportunidadesService } from '../oportunidades/oportunidades.service';
import { ReportesCrmService } from './reportes-crm.service';

@ApiTags('CRM · Reportes')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), SubmoduloGuard)
@RequireSubmodulo('CRM_REPORTES')
@Controller({ path: 'crm/reportes', version: '1' })
export class ReportesCrmController {
  constructor(
    private readonly service: ReportesCrmService,
    private readonly oportunidades: OportunidadesService,
    private readonly prisma: PrismaService,
  ) {}

  /**
   * Mismo cálculo que el controller de oportunidades: sin `VER_AJENAS` el
   * reporte muestra el embudo del propio vendedor, no el de la empresa.
   */
  private async alcance(user: LoginUserInfo) {
    const verAjenas = await this.prisma.perfiles_privilegios.findFirst({
      where: {
        privilegios: { codigo: 'CRM_OPO_OPORTUNIDAD_VER_AJENAS' },
        perfiles: { usuario_perfiles: { some: { user_id: user.id } } },
      },
      select: { id: true },
    });
    return this.oportunidades.resolverAlcance(user.empresa_id, user.id, !!verAjenas);
  }

  @Get()
  @UseGuards(PermissionGuard)
  @RequirePermission('CRM', 'CRM_REP_REPORTE_VER')
  @ApiQuery({ name: 'desde', required: false, example: '2026-01-01' })
  @ApiQuery({ name: 'hasta', required: false, example: '2026-12-31' })
  @ApiQuery({ name: 'pipeline_id', required: false })
  @ApiOperation({ summary: 'Los cinco reportes de F1 en una sola llamada (dashboard)' })
  async resumen(@GetUser() user: LoginUserInfo, @Query() q: Record<string, string>) {
    return this.service.resumen(user.empresa_id, await this.alcance(user), q);
  }

  @Get('pipeline')
  @UseGuards(PermissionGuard)
  @RequirePermission('CRM', 'CRM_REP_REPORTE_VER')
  @ApiQuery({ name: 'pipeline_id', required: false })
  @ApiOperation({ summary: 'Embudo por etapa con valor ponderado (forecast)' })
  async pipeline(@GetUser() user: LoginUserInfo, @Query() q: Record<string, string>) {
    return this.service.pipeline(user.empresa_id, await this.alcance(user), q);
  }

  @Get('conversion')
  @UseGuards(PermissionGuard)
  @RequirePermission('CRM', 'CRM_REP_REPORTE_VER')
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  @ApiOperation({
    summary: 'Conversión por origen',
    description: 'La tasa se calcula sobre oportunidades cerradas: las abiertas todavía no fracasaron.',
  })
  async conversion(@GetUser() user: LoginUserInfo, @Query() q: Record<string, string>) {
    return this.service.conversion(user.empresa_id, await this.alcance(user), q);
  }

  @Get('motivos-perdida')
  @UseGuards(PermissionGuard)
  @RequirePermission('CRM', 'CRM_REP_REPORTE_VER')
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  @ApiOperation({ summary: 'Por qué se pierde, ordenado por frecuencia' })
  async motivos(@GetUser() user: LoginUserInfo, @Query() q: Record<string, string>) {
    return this.service.motivosPerdida(user.empresa_id, await this.alcance(user), q);
  }

  @Get('vendedores')
  @UseGuards(PermissionGuard)
  @RequirePermission('CRM', 'CRM_REP_REPORTE_VER')
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  @ApiOperation({ summary: 'Ranking por monto ganado y tasa de cierre' })
  async vendedores(@GetUser() user: LoginUserInfo, @Query() q: Record<string, string>) {
    return this.service.vendedores(user.empresa_id, await this.alcance(user), q);
  }

  @Get('ciclo-venta')
  @UseGuards(PermissionGuard)
  @RequirePermission('CRM', 'CRM_REP_REPORTE_VER')
  @ApiQuery({ name: 'desde', required: false })
  @ApiQuery({ name: 'hasta', required: false })
  @ApiOperation({
    summary: 'Días entre alta y cierre',
    description: 'Devuelve promedio y mediana: el promedio solo lo distorsiona una venta larga.',
  })
  async ciclo(@GetUser() user: LoginUserInfo, @Query() q: Record<string, string>) {
    return this.service.cicloVenta(user.empresa_id, await this.alcance(user), q);
  }
}
