import _ from 'lodash';

import { convertIntoDates } from '../helpers/column-desciptions.helper';
import { ECollaterals } from '../enums/collaterals.enum';
import { ELoanTransactionTypes, ILoanTransactionUpload } from '../models/LoanTransaction.model';
import { LoanProduct } from '../models/LoanProducts.model';
import { BorrowerModel } from '../models/Borrower.model';
import { BanksService } from '../services/banks.service';
import { LoanChargesService } from '../services/loan-charges.service';
import { BorrowersDB } from '../services/borrowers.db';

export class LoanTransactionItem implements ILoanTransactionUpload {

  amount = 0;
  customerId = '';
  date = new Date();
  description = '';
  ledgerAccountCode = '';
  reference = '';
  bankAccountNumber = '';
  transactionType: ELoanTransactionTypes = null;
  isStatement = false;

  constructor(
    item: Partial<ILoanTransactionUpload>,
    private readonly borrowersDB: BorrowersDB,
  ) {
    const itemWithDates = convertIntoDates(item, ECollaterals.LOAN_TRANSACTIONS);
    const itemWithoutNulls = _.omitBy(itemWithDates, (value) => value === null);
    this.transactionType = item.amount < 0 ? ELoanTransactionTypes.COLLECTION : ELoanTransactionTypes.DISBURSEMENT;
    Object.assign(this, itemWithoutNulls);
  }

  async initialize() {
    return await this.validateData();
  }

  async validateData() {
    const errors = [];
    const banksService: BanksService = new BanksService();
    const foundBank = await banksService.findBankByNumber(this.bankAccountNumber);
    const loanChargesService: LoanChargesService = new LoanChargesService(this.borrowersDB);
    const foundProductId = await loanChargesService.getLoanProductIdByCode(this.ledgerAccountCode);
    const foundChargeId = await loanChargesService.getLoanChargeIdByCode(this.ledgerAccountCode);
    if (foundChargeId) {
      this.isStatement = true;
    }
    if (!foundBank) {
      errors.push({ bankAccountNumber: [{ error: `no bank with this code` }] });
    }
    if (!foundProductId && !foundChargeId) {
      errors.push({ ledgerAccountCode: [{ error: `no product with this code` }] });
    }
    if (foundProductId) {
      const product = await LoanProduct.findById(foundProductId).lean();
      if (product) {
        const borrower = await BorrowerModel.findById(product.borrowerId).lean();
        if (!borrower.active) {
          errors.push({ borrower: [{ error: `borrower is not active` }] });
        }
      }
    }
    return errors;
  }

}
