import {
  Body,
  Controller,
  Param,
  Patch,
  Post,
  Request,
  Res,
  UseGuards,
} from '@nestjs/common';
import type { Response, Request as ExpressRequest } from 'express';
import { Public } from '@common/decorators/public.decorator';
import { SkipTransform } from '@common/decorators/skip-transform.decorator';
import { CheckinService } from '../services/checkin.service';
import { handleMeetingAttendanceError } from '../errors/handle-controller-error';
import { getMeetingRoleFromUser, isMeetingAdminRole } from '../utils/meeting-roles';

@Controller('meeting-attendance/meetings')
@SkipTransform()
export class MeetingAttendanceCheckinController {
  constructor(private readonly checkinService: CheckinService) {}

  @Post(':id/checkin')
  async checkin(
    @Param('id') id: string,
    @Body() body: Record<string, any>,
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    try {
      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) {
        return res.status(401).json({ error: 'Unauthorized' });
      }

      const role = getMeetingRoleFromUser(user);
      if (!role) {
        return res.status(403).json({ error: 'Insufficient permissions' });
      }

      const result = await this.checkinService.checkin(id, body, userId);
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Check-in failed, please try again later');
    }
  }

  @Post(':id/guest-checkin')
  @Public()
  async guestCheckin(
    @Param('id') id: string,
    @Body() body: Record<string, any>,
    @Res() res: Response,
  ) {
    try {
      const result = await this.checkinService.guestCheckin(id, body as any);
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Check-in failed, please try again later');
    }
  }

  @Patch(':id/attendance/:userId')
  async updateAttendanceStatus(
    @Param('id') meetingId: string,
    @Param('userId') userId: string,
    @Body() body: Record<string, any>,
    @Request() req: ExpressRequest,
    @Res() res: Response,
  ) {
    try {
      const meetingUserRole = await this.requireAdminOrManager(req, res);
      if (!meetingUserRole) {
        return res;
      }

      const actor = req.user as any;
      const result = await this.checkinService.updateAttendanceStatus(
        meetingId,
        userId,
        body as any,
        req,
        actor,
      );
      return res.status(200).json(result);
    } catch (error) {
      return handleMeetingAttendanceError(res, error, 'Failed to update attendance status');
    }
  }

  private async requireAdminOrManager(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 access' });
      return null;
    }

    const role = getMeetingRoleFromUser(user);
    if (!isMeetingAdminRole(role)) {
      res.status(403).json({ error: 'Insufficient permissions' });
      return null;
    }

    return role;
  }
}
