import {
  CanActivate,
  ExecutionContext,
  Injectable,
  ForbiddenException,
} from "@nestjs/common"
import { failureResponse } from "../response/response"
import { errorMessage } from "../../utils/helpers"
import { messageKey } from "../../constants/message-keys"
import { AuthService } from "../../modules/auth/auth.service"
import { SubscriptionRepository } from "../../modules/subscriptions/repository/subscription.repository"
import { getCurrentEnvironment } from "../../utils/helpers"
import moment from "moment"

@Injectable()
export class SubscriptionGuard implements CanActivate {
  constructor(
    private readonly authService: AuthService,
    private readonly subscriptionRepository: SubscriptionRepository,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    if (getCurrentEnvironment() === "local") {
      return true
    }

    const request = context.switchToHttp().getRequest()
    const token = request.headers["authorization"]

    if (!token) return true

    const loggedInUser = await this.authService.getUserByToken(token)
    if (!loggedInUser) return true

    const subscription: any = await this.subscriptionRepository.getByParams({
      where: { user_id: loggedInUser.user_id },
      orderBy: { created_at: "DESC" },
      findOne: true,
    })

    if (!subscription) {
      throw new ForbiddenException(
        failureResponse(
          403,
          errorMessage(messageKey.active_subscription_required),
        ),
      )
    }

    const now = moment.utc()

    // Active premium subscription
    if (subscription.status === "active") {
      if (subscription.cancel_at_period_end) {
        const periodEnd = moment(subscription.current_period_end)
        if (now.isAfter(periodEnd)) {
          throw new ForbiddenException(
            failureResponse(
              403,
              errorMessage(messageKey.active_subscription_required),
            ),
          )
        }
      }
      return true
    }

    // Active trial
    if (subscription.status === "trialing") {
      const trialEnd = moment(subscription.trial_end)
      if (now.isBefore(trialEnd)) {
        return true
      }
      throw new ForbiddenException(
        failureResponse(
          403,
          errorMessage(messageKey.active_subscription_required),
        ),
      )
    }

    throw new ForbiddenException(
      failureResponse(
        403,
        errorMessage(messageKey.active_subscription_required),
      ),
    )
  }
}
