import {
  CanActivate,
  ExecutionContext,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { JwtService } from '@nestjs/jwt';
import { Admin, AdminDocument } from '../../schema/admin.schema';
import { ADMIN, USER } from 'src/utils/constants';
import { User, UserDocument } from 'src/schema/user.schema';

@Injectable()
export class AdminGuard implements CanActivate {
  constructor(
    @InjectModel(Admin.name) private adminModel: Model<AdminDocument>,
    @InjectModel(User.name) private userModel: Model<UserDocument>,
    private readonly jwtService: JwtService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<any> {
    try {
      const request = context?.switchToHttp()?.getRequest();
      if (!request?.headers || !request?.headers?.authorization) {
        throw new UnauthorizedException('Authentication failed.');
      }
      const token = request?.headers?.authorization?.split(' ')[1];
      if (!token) {
        throw new UnauthorizedException('Authentication failed.');
      }
      const decode = await this.jwtService.verify(token, {
        secret: process.env.JWT_SECRET_KEY,
      });
      if (!decode) {
        throw new UnauthorizedException('Authentication failed.');
      }
      if (decode?.role && decode?.role === ADMIN) {
        const admin = await this.adminModel
          .findById(decode?.id)
          .select({ password: 0 });
        if (!admin) {
          throw new UnauthorizedException('Authentication failed.');
        }
        request['admin'] = admin;
        return true;
      } else if (decode?.role && decode?.role === USER) {
        const user = await this.userModel
          .findById(decode?.id)
          .select({ password: 0 });
        if (!user || !user?.is_admin || user?.is_blocked) {
          throw new UnauthorizedException('Authentication failed.');
        }
        request['admin'] = user;
        return true;
      } else {
        throw new UnauthorizedException('Authentication failed.');
      }
    } catch (error) {
      throw new UnauthorizedException('Authentication failed.');
    }
  }
}
