import {
  CanActivate,
  ExecutionContext,
  Injectable,
  UnprocessableEntityException,
} from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { OtpVerificationModel } from 'src/modules/configuration/otp-verification/data/models/otp-verification.model';
import { OtpVerificationEntity } from 'src/modules/configuration/otp-verification/domain/entities/otp-verification.entity';
import { DataSource } from 'typeorm';

@Injectable()
export class OtpCheckerGuard implements CanActivate {
  constructor(
    @InjectDataSource(CONNECTION_NAME.DEFAULT)
    protected readonly dataSource: DataSource,
  ) {}

  get otpRepository() {
    return this.dataSource.getRepository(OtpVerificationModel);
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const verificationCode = request.headers['x-verification-code'];
    console.log({ verificationCode });

    if (verificationCode) {
      const decoded = Buffer.from(verificationCode, 'base64').toString('ascii');
      const [dataIdentity, otpCode] = decoded.split('|');

      let otpData: OtpVerificationEntity;

      otpData = await this.otpRepository.findOne({
        where: {
          otp_code: otpCode,
          target_id: dataIdentity,
        },
      });

      if (!otpData) {
        otpData = await this.otpRepository.findOne({
          where: {
            otp_code: otpCode,
            reference: dataIdentity,
          },
        });
      }

      // console.log({ dataIdentity, otpCode, otpData });
      if (otpData && otpData?.verified_at) return true;
    }

    throw new UnprocessableEntityException('OTP not verified.');
  }
}
