import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { TripMembersRepository } from './trip-members.repository';
import { TRIP_ROLES_KEY } from './trip-roles.decorator';
import type { TripRole } from './trip-roles.decorator';

interface RequestWithTripMembership {
  params: Record<string, string>;
  user: { id: string };
  tripMembership?: { role: string; status: string };
}

@Injectable()
export class TripMembershipGuard implements CanActivate {
  constructor(
    private readonly tripMembers: TripMembersRepository,
    private readonly reflector: Reflector,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredRoles = this.reflector.getAllAndOverride<
      TripRole[] | undefined
    >(TRIP_ROLES_KEY, [context.getHandler(), context.getClass()]);

    const request = context
      .switchToHttp()
      .getRequest<RequestWithTripMembership>();
    const tripId = request.params.tripId;
    const membership = await this.tripMembers.findByTripAndUser(
      tripId,
      request.user.id,
    );

    if (!membership || membership.status !== 'ACTIVE') {
      throw new ForbiddenException('You are not an active member of this trip');
    }

    if (
      requiredRoles &&
      requiredRoles.length > 0 &&
      !requiredRoles.includes(membership.role)
    ) {
      throw new ForbiddenException(
        'You do not have the required role for this action',
      );
    }

    request.tripMembership = {
      role: membership.role,
      status: membership.status,
    };
    return true;
  }
}
