import { Injectable } from '@nestjs/common';
import { CreateTransactionManager } from './managers/create-transaction.manager';
import { TransactionDataService } from '../../data/services/transaction-data.service';
import { TransactionEntity } from '../entities/transaction.entity';
import { DeleteTransactionManager } from './managers/delete-transaction.manager';
import { UpdateTransactionManager } from './managers/update-transaction.manager';
import { ConfirmTransactionManager } from './managers/confirm-transaction.manager';
import { STATUS } from 'src/core/strings/constants/base.constants';
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
import { BatchConfirmTransactionManager } from './managers/batch-confirm-transaction.manager';
import { BatchDeleteTransactionManager } from './managers/batch-delete-transaction.manager';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { CancelTransactionManager } from './managers/cancel-transaction.manager';
import { BatchCancelTransactionManager } from './managers/batch-cancel-transaction.manager';
import { ConfirmDataTransactionManager } from './managers/confirm-data-transaction.manager';
import { BatchConfirmDataTransactionManager } from './managers/batch-confirm-data-transaction.manager';
import { MidtransService } from 'src/modules/configuration/midtrans/data/services/midtrans.service';
import { PdfMakeManager } from 'src/modules/configuration/export/domain/managers/pdf-make.manager';
import { PaymentMethodDataService } from 'src/modules/transaction/payment-method/data/services/payment-method-data.service';

@Injectable()
export class TransactionDataOrchestrator {
  constructor(
    private createManager: CreateTransactionManager,
    private updateManager: UpdateTransactionManager,
    private confirmManager: ConfirmTransactionManager,
    private batchConfirmManager: BatchConfirmTransactionManager,
    private confirmDataManager: ConfirmDataTransactionManager,
    private batchConfirmDataManager: BatchConfirmDataTransactionManager,
    private deleteManager: DeleteTransactionManager,
    private batchDeleteManager: BatchDeleteTransactionManager,
    private cancelManager: CancelTransactionManager,
    private batchCancelManager: BatchCancelTransactionManager,
    private invoiceManager: PdfMakeManager,
    private serviceData: TransactionDataService,
    private paymentMethodService: PaymentMethodDataService,
    private midtransService: MidtransService,
  ) {}

  async create(data): Promise<TransactionEntity> {
    this.createManager.setData(data);
    this.createManager.setService(this.serviceData, TABLE_NAME.TRANSACTION);
    await this.createManager.execute();
    return this.createManager.getResult();
  }

  async update(dataId, data): Promise<TransactionEntity> {
    this.updateManager.setData(dataId, data);
    this.updateManager.setService(this.serviceData, TABLE_NAME.TRANSACTION);
    await this.updateManager.execute();
    return this.updateManager.getResult();
  }

  async invoice(dataId, invoiceType): Promise<any> {
    this.invoiceManager.setData({
      id: dataId,
      invoice_type: invoiceType,
    });
    this.invoiceManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
      this.paymentMethodService,
    );
    await this.invoiceManager.execute();
    return this.invoiceManager.getResult();
  }

  async delete(dataId): Promise<string> {
    this.deleteManager.setData(dataId);
    this.deleteManager.setService(this.serviceData, TABLE_NAME.TRANSACTION);
    await this.deleteManager.execute();
    return this.deleteManager.getResult();
  }

  async batchDelete(dataIds: string[]): Promise<BatchResult> {
    this.batchDeleteManager.setData(dataIds);
    this.batchDeleteManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
    );
    await this.batchDeleteManager.execute();
    return this.batchDeleteManager.getResult();
  }

  async cancel(dataId): Promise<string> {
    this.cancelManager.setData(dataId, STATUS.CANCEL);
    this.cancelManager.setService(this.serviceData, TABLE_NAME.TRANSACTION);
    await this.cancelManager.execute();
    return this.cancelManager.getResult();
  }

  async batchCancel(dataIds: string[]): Promise<BatchResult> {
    this.batchCancelManager.setData(dataIds, STATUS.CANCEL);
    this.batchCancelManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
    );
    await this.batchCancelManager.execute();
    return this.batchCancelManager.getResult();
  }

  // Confirm from draft to pending
  async confirm(dataId): Promise<string> {
    this.confirmManager.setData(dataId, STATUS.ACTIVE);
    this.confirmManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
      this.midtransService,
    );
    await this.confirmManager.execute();
    return this.confirmManager.getResult();
  }

  async batchConfirm(dataIds: string[]): Promise<BatchResult> {
    this.batchConfirmManager.setData(dataIds, STATUS.PENDING);
    this.batchConfirmManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
      this.midtransService,
    );
    await this.batchConfirmManager.execute();
    return this.batchConfirmManager.getResult();
  }

  async confirmData(dataId): Promise<string> {
    this.confirmDataManager.setData(dataId, STATUS.ACTIVE);
    this.confirmDataManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
    );
    await this.confirmDataManager.execute();
    return this.confirmDataManager.getResult();
  }

  async batchConfirmData(dataIds: string[]): Promise<BatchResult> {
    this.batchConfirmDataManager.setData(dataIds, STATUS.ACTIVE);
    this.batchConfirmDataManager.setService(
      this.serviceData,
      TABLE_NAME.TRANSACTION,
    );
    await this.batchConfirmDataManager.execute();
    return this.batchConfirmDataManager.getResult();
  }

  async saveTransactionToCouch(transaction: any[]) {
    for (const t of transaction) {
      await this.serviceData.saveTransactionToCouch(t);
    }
  }
}
