import { Injectable, UnprocessableEntityException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RescheduleVerificationModel } from '../../../data/models/reschedule-verification.model';
import {
  RescheduleRequest,
  RescheduleVerification,
} from '../../entities/reschedule-verification.entity';
import { generateOtp } from 'src/modules/booking-online/helpers/generate-otp';
import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service';
import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity';
import { WhatsappService } from 'src/services/whatsapp/whatsapp.service';

@Injectable()
export class RescheduleVerificationManager {
  constructor(
    @InjectRepository(RescheduleVerificationModel)
    private readonly rescheduleVerificationRepository: Repository<RescheduleVerificationModel>,
    private readonly transactionService: TransactionReadService,
  ) {}

  async saveVerification(
    request: RescheduleRequest,
  ): Promise<RescheduleVerificationModel> {
    try {
      const otp = generateOtp();
      const transaction = await this.findDetailByBookingId(request.booking_id);

      if (!transaction) {
        throw new Error('Transaction not found for the provided booking id');
      }

      const data: Partial<RescheduleVerification> = {
        code: otp,
        booking_id: transaction.id,
        name: transaction.customer_name,
        phone_number: transaction.customer_phone,
        reschedule_date: request.reschedule_date,
      };

      const existTransaction =
        await this.rescheduleVerificationRepository.findOne({
          where: {
            booking_id: transaction.id,
          },
        });

      const verification =
        existTransaction ?? this.rescheduleVerificationRepository.create(data);
      const result = await this.rescheduleVerificationRepository.save({
        ...verification,
        code: otp,
      });

      const whatsapp = new WhatsappService();
      whatsapp.sendOtpNotification({
        phone: transaction.customer_phone,
        code: otp.toString(),
      });
      //   whatsapp.bookingRescheduleOTP({
      //     phone: transaction.customer_phone,
      //     code: otp.toString(),
      //     name: transaction.customer_name,
      //     time: new Date(request.reschedule_date).getTime(),
      //     id: transaction.id,
      //   });
      return result;
    } catch (error) {
      // You can customize the error handling as needed, e.g., throw HttpException for NestJS
      throw new UnprocessableEntityException(
        `Failed to save reschedule verification: ${error.message}`,
      );
    }
  }

  async verifyOtp(
    booking_id: string,
    code: number,
  ): Promise<RescheduleVerificationModel> {
    const verification = await this.rescheduleVerificationRepository.findOne({
      where: { booking_id, code },
      order: { created_at: 'DESC' },
    });

    if (!verification) {
      throw new UnprocessableEntityException({
        success: false,
        message: 'Verification code not match',
      });
    }

    // Optionally, you can implement OTP expiration logic here

    if (verification.code !== code) {
      // Increment tried count
      verification.tried = (verification.tried || 0) + 1;
      await this.rescheduleVerificationRepository.save(verification);
      throw new UnprocessableEntityException({
        success: false,
        message: 'Invalid verification code.',
      });
    }

    // Optionally, you can mark the verification as used or verified here

    return verification;
  }

  async findDetailByBookingId(bookingId: string): Promise<TransactionEntity> {
    const transaction = await this.transactionService.getOneByOptions({
      where: { id: bookingId },
    });
    return transaction;
  }
}
