import {
  Controller,
  Get,
  Query,
  Request,
  Res,
  UseGuards,
} from '@nestjs/common';
import type { Response, Request as ExpressRequest } from 'express';
import { SkipTransform } from '@common/decorators/skip-transform.decorator';
import { ReportsService } from '../services/reports.service';
import { handleMeetingAttendanceError } from '../errors/handle-controller-error';
import { getMeetingRoleFromUser } from '../utils/meeting-roles';

@Controller('meeting-attendance/reports')
@SkipTransform()
export class MeetingAttendanceReportsController {
  constructor(private readonly reportsService: ReportsService) {}

  @Get('attendance')
  async getAttendanceReport(
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    try {
      const actor = await this.requireReportUser(req, res);
      if (!actor) {
        return res;
      }

      const result = await this.reportsService.getAttendanceReport();
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Server error', 'MeetingAttendanceReportsController');
    }
  }

  @Get('series-options')
  async getSeriesOptions(
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    try {
      const actor = await this.requireReportUser(req, res);
      if (!actor) {
        return res;
      }

      const result = await this.reportsService.listSeriesOptions();
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Server error', 'MeetingAttendanceReportsController');
    }
  }

  @Get('series')
  async getSeriesReport(
    @Query() query: Record<string, any>,
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    try {
      const actor = await this.requireReportUser(req, res);
      if (!actor) {
        return res;
      }

      const includeLegacyRaw = query.includeLegacy;
      const includeLegacy =
        includeLegacyRaw === undefined
          ? undefined
          : includeLegacyRaw !== '0' && includeLegacyRaw !== 'false';

      const result = await this.reportsService.getSeriesReport({
        seriesId: query.seriesId,
        startDate: query.startDate,
        endDate: query.endDate,
        includeLegacy,
      });
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Server error', 'MeetingAttendanceReportsController');
    }
  }

  @Get('single-meeting')
  async getSingleMeetingReport(
    @Query() query: Record<string, any>,
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    try {
      const actor = await this.requireReportUser(req, res);
      if (!actor) {
        return res;
      }

      const result = await this.reportsService.getSingleMeetingReport({ meetingId: query.meetingId });
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Server error', 'MeetingAttendanceReportsController');
    }
  }

  private async requireReportUser(req: ExpressRequest, res: Response) {
    const user = req.user as
      | { userId?: string; id?: string; email?: string; roles?: Array<{ role?: { code?: string } } | string> }
      | undefined;
    const userId = user?.userId ?? user?.id;
    if (!userId || !user?.email) {
      res.status(401).json({ error: 'Unauthorized' });
      return null;
    }

    const role = getMeetingRoleFromUser(user);
    if (!role || !['Administrator', 'MeetingManager', 'Leader'].includes(role)) {
      res.status(403).json({ error: 'Insufficient permissions' });
      return null;
    }

    return { id: userId, role, email: user.email };
  }
}
