import { Injectable } from '@nestjs/common';
import { mappingMidtransTransaction } from '../../domain/usecases/helpers/mapping-transaction.helper';
import { Snap } from 'midtrans-client';
import { MidtransStatus } from '../../domain/entities/midtrans-callback.event';
import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service';

import * as moment from 'moment';

@Injectable()
export class MidtransService {
  constructor(private transaction: TransactionReadService) {}

  isMoreThan24HoursAgo(dateString) {
    const date = moment(dateString, 'YYYY-MM-DD', true);
    if (!date.isValid()) {
      return false;
    }

    const now = moment();
    const diffInHours = now.diff(date, 'hours');
    return diffInHours > 24;
  }

  isCreatedMoreThan24HoursAgo(unixTimestamp) {
    const date = moment.unix(unixTimestamp);
    const now = moment();
    const diffInHours = now.diff(date, 'hours');
    return diffInHours > 24;
  }

  isBookingDateExpired(bookingDate) {
    const bookingDateMoment = moment(bookingDate);
    const today = moment().startOf('day');
    return bookingDateMoment.isBefore(today);
  }

  get midtransInstance() {
    return new Snap({
      isProduction: false,
      serverKey: process.env.MIDTRANS_SERVER_KEY,
      clientKey: process.env.MIDTRANS_CLIENT_KEY,
    });
  }

  async getStatus(orderId: string): Promise<any> {
    return await this.midtransInstance.transaction.status(orderId);
  }

  async syncPendingStatus(): Promise<any[]> {
    const pendingIds = await this.transaction.getPendingOrderId();
    const responses = [];

    for (const transaction of pendingIds) {
      const { id, booking_date, created_at } = transaction;
      let status;
      try {
        status = await this.getStatus(id);
      } catch (error) {
        status = {
          order_id: id,
          transaction_status:
            this.isCreatedMoreThan24HoursAgo(created_at) ||
            this.isBookingDateExpired(booking_date)
              ? 'expired'
              : 'pending',
        };
      }
      responses.push(status);
    }
    return responses;
  }

  async changeStatus(orderId: string, action: MidtransStatus): Promise<any> {
    return await this.midtransInstance.transaction[action](orderId);
  }

  async create(body): Promise<any> {
    const data = mappingMidtransTransaction(body);
    return await this.midtransInstance.createTransaction(data);
  }
}
