import { Controller, Get, Param, Query, Req, Res, ParseIntPipe, UseGuards, UsePipes, ValidationPipe } from '@nestjs/common';
import { Response } from 'express';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiSecurity, ApiParam } from '@nestjs/swagger';
import { ResponseService } from 'src/common/response-handling/response-handler';
import { handleControllerError } from 'src/common/utils/controller-response-handling';
import { RolesGuard } from 'src/common/guards/roles.guard';
import { Roles } from 'src/common/decorators/roles.decorator';
import { ROLE_VALUES } from 'src/common/constants/strings-constants';
import { CombinedAuthGuard } from 'src/auth/combined-auth.guard';
import { AuthenticatedRequest } from 'src/common/interfaces/authenticated-request.interface';
import { ZoomAnalyticsFacadeService } from 'src/zoom/services/zoom-analytics-facade.service';
import { AnalyticsAttendeeQueryV1Dto } from '../dto/analytics-attendee-query-v1.dto';
import { AnalyticsGeneralAttendeeQueryV1Dto } from '../dto/analytics-general-attendee-query-v1.dto';
import { ANALYTICS_SWAGGER, ANALYTICS_V1_SWAGGER, ANALYTICS_V1_RESPONSE } from '../constants/analytics.constants';

/**
 * v1 session-analytics API — filters, clickable KPIs, table headers, and RM scoping on top of the
 * unversioned `analytics/sessions` routes (kept live alongside this, see the design doc's deprecation
 * open question). Same zero-DB-access boundary as AnalyticsController: every read goes through
 * ZoomAnalyticsFacadeService.
 */
@ApiTags(ANALYTICS_SWAGGER.TAG)
@Controller('v1/analytics/sessions')
@UseGuards(CombinedAuthGuard, RolesGuard)
@Roles('admin', 'shoba', 'relational_manager')
@ApiBearerAuth('Authorization')
@ApiSecurity('userIdAuth')
@ApiSecurity('activeRoleAuth')
export class AnalyticsV1Controller {
  constructor(
    private readonly facade: ZoomAnalyticsFacadeService,
    private readonly responseService: ResponseService,
  ) {}

  @Get(':sessionId/kpis')
  @Roles('admin', ROLE_VALUES.RELATIONAL_MANAGER, ROLE_VALUES.COORDINATOR)
  @ApiOperation({ summary: ANALYTICS_V1_SWAGGER.GET_KPIS })
  @ApiParam({ name: 'sessionId', type: Number })
  async getKpis(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Req() req: AuthenticatedRequest,
    @Res() res: Response,
  ) {
    try {
      const data = await this.facade.getKpisV1(sessionId, req.user?.roles ?? [], req.user?.id ?? null);
      await this.responseService.success(res, ANALYTICS_V1_RESPONSE.KPIS_FETCHED, data);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  @Get(':sessionId/live')
  @Roles('admin', ROLE_VALUES.RELATIONAL_MANAGER, ROLE_VALUES.COORDINATOR)
  @UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
  @ApiOperation({ summary: ANALYTICS_V1_SWAGGER.GET_LIVE })
  @ApiParam({ name: 'sessionId', type: Number })
  async getLive(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Query() query: AnalyticsAttendeeQueryV1Dto,
    @Req() req: AuthenticatedRequest,
    @Res() res: Response,
  ) {
    try {
      const data = await this.facade.getLiveStatusV1(sessionId, query, req.user?.roles ?? [], req.user?.id ?? null);
      await this.responseService.success(res, ANALYTICS_V1_RESPONSE.LIVE_FETCHED, data);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  @Get(':sessionId/attendees')
  @Roles('admin', ROLE_VALUES.RELATIONAL_MANAGER, ROLE_VALUES.COORDINATOR)
  @UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
  @ApiOperation({ summary: ANALYTICS_V1_SWAGGER.GET_ATTENDEES })
  @ApiParam({ name: 'sessionId', type: Number })
  async getAttendees(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Query() query: AnalyticsAttendeeQueryV1Dto,
    @Req() req: AuthenticatedRequest,
    @Res() res: Response,
  ) {
    try {
      const data = await this.facade.getAttendeeTableV1(
        sessionId,
        query,
        req.user?.roles ?? [],
        req.user?.id ?? null,
      );
      await this.responseService.success(res, ANALYTICS_V1_RESPONSE.ATTENDEES_FETCHED, data);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  @Get(':sessionId/general-attendees/kpis')
  @Roles('admin', ROLE_VALUES.RELATIONAL_MANAGER, ROLE_VALUES.COORDINATOR)
  @ApiOperation({ summary: ANALYTICS_V1_SWAGGER.GET_GENERAL_KPIS })
  @ApiParam({ name: 'sessionId', type: Number })
  async getGeneralKpis(@Param('sessionId', ParseIntPipe) sessionId: number, @Res() res: Response) {
    try {
      const data = await this.facade.getGeneralKpisV1(sessionId);
      await this.responseService.success(res, ANALYTICS_V1_RESPONSE.GENERAL_KPIS_FETCHED, data);
    } catch (error) {
      handleControllerError(res, error);
    }
  }

  @Get(':sessionId/general-attendees')
  @Roles('admin', ROLE_VALUES.RELATIONAL_MANAGER, ROLE_VALUES.COORDINATOR)
  @UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
  @ApiOperation({ summary: ANALYTICS_V1_SWAGGER.GET_GENERAL_ATTENDEES })
  @ApiParam({ name: 'sessionId', type: Number })
  async getGeneralAttendees(
    @Param('sessionId', ParseIntPipe) sessionId: number,
    @Query() query: AnalyticsGeneralAttendeeQueryV1Dto,
    @Req() req: AuthenticatedRequest,
    @Res() res: Response,
  ) {
    try {
      const data = await this.facade.getGeneralAttendeesV1(
        sessionId,
        query,
        req.user?.roles ?? [],
        req.user?.id ?? null,
      );
      await this.responseService.success(res, ANALYTICS_V1_RESPONSE.GENERAL_ATTENDEES_FETCHED, data);
    } catch (error) {
      handleControllerError(res, error);
    }
  }
}
