/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.fineract.cn.deposit.service.internal.service;

import org.apache.commons.lang.StringUtils;
import org.apache.fineract.cn.accounting.api.v1.client.LedgerManager;
import org.apache.fineract.cn.accounting.api.v1.domain.Account;
import org.apache.fineract.cn.accounting.api.v1.domain.Creditor;
import org.apache.fineract.cn.accounting.api.v1.domain.Debtor;
import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
import org.apache.fineract.cn.api.util.UserContextHolder;
import org.apache.fineract.cn.deposit.api.v1.definition.domain.Action;
import org.apache.fineract.cn.deposit.api.v1.definition.domain.Charge;
import org.apache.fineract.cn.deposit.api.v1.definition.domain.Currency;
import org.apache.fineract.cn.deposit.api.v1.definition.domain.ProductDefinition;
import org.apache.fineract.cn.deposit.api.v1.instance.domain.ProductInstance;
import org.apache.fineract.cn.deposit.api.v1.instance.domain.SubTransactionType;
import org.apache.fineract.cn.deposit.api.v1.transaction.domain.data.*;
import org.apache.fineract.cn.deposit.api.v1.transaction.utils.MathUtil;
import org.apache.fineract.cn.deposit.service.ServiceConstants;
import org.apache.fineract.cn.deposit.service.internal.command.TransactionCommand;
import org.apache.fineract.cn.deposit.service.internal.repository.ProductInstanceEntity;
import org.apache.fineract.cn.deposit.service.internal.repository.ProductInstanceRepository;
import org.apache.fineract.cn.deposit.service.internal.repository.TransactionEntity;
import org.apache.fineract.cn.deposit.service.internal.repository.TransactionRepository;
import org.apache.fineract.cn.lang.DateConverter;
import org.apache.fineract.cn.lang.ServiceException;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.math.MathContext;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TransactionService {
    private final Logger logger;
    private final LedgerManager ledgerManager;
    private final ProductInstanceService productInstanceService;
    private final ProductDefinitionService productDefinitionService;
    private final ActionService actionService;
    private final SubTxnTypesService subTxnTypesService;
    private final TransactionRepository transactionRepository;
    private final ProductInstanceRepository productInstanceRepository;

    public static final String DEBIT = "DEBIT";
    public static final String CREDIT = "CREDIT";

    @Autowired
    public TransactionService(@Qualifier(ServiceConstants.LOGGER_NAME) Logger logger, LedgerManager ledgerManager,
                              ProductInstanceService productInstanceService,
                              ProductDefinitionService productDefinitionService, ActionService actionService,
                              SubTxnTypesService subTxnTypesService, TransactionRepository transactionRepository, ProductInstanceRepository productInstanceRepository) {
        this.logger = logger;
        this.ledgerManager = ledgerManager;
        this.productInstanceService = productInstanceService;
        this.productDefinitionService = productDefinitionService;
        this.actionService = actionService;
        this.subTxnTypesService = subTxnTypesService;
        this.transactionRepository = transactionRepository;
        this.productInstanceRepository = productInstanceRepository;
    }

    @Transactional
    public TransactionResponseData withdraw(TransactionCommand command) {
        TransactionRequestData request = command.getTransactionRequest();
        AccountWrapper accountWrapper = validateAndGetAccount(request, request.getAccountId(), TransactionTypeEnum.WITHDRAWAL);
        LocalDateTime transactionDate = getNow();
        //get txntype charges
        List<Charge> charges = getCharges(accountWrapper.account.getIdentifier(), TransactionTypeEnum.WITHDRAWAL);
        //todo: get subTxnType charges

        TransactionEntity txn = doWithdraw(request, accountWrapper, charges, getNow(), request.getAccountId());


        return TransactionResponseData.build(request.getRoutingCode(), request.getExternalId(),
                request.getRequestCode(), ActionState.ACCEPTED,
                null, txn.getIdentifier(), transactionDate);
    }

    @Transactional
    public TransactionResponseData deposit(TransactionCommand command) {
        TransactionRequestData request = command.getTransactionRequest();
        AccountWrapper accountWrapper = validateAndGetAccount(request, request.getAccountId(), TransactionTypeEnum.DEPOSIT);
        LocalDateTime transactionDate = getNow();
        //get txntype charges
        List<Charge> charges = getCharges(accountWrapper.account.getIdentifier(), TransactionTypeEnum.DEPOSIT);
        //todo: get subTxnType charges
        TransactionEntity txn = doDeposit(request, accountWrapper, charges, getNow(), request.getAccountId());

        return TransactionResponseData.build(request.getRoutingCode(), request.getExternalId(),
                request.getRequestCode(), ActionState.ACCEPTED,
                null, txn.getIdentifier(), transactionDate);
    }

    public TransactionResponseData transfer(TransactionCommand command) {
        TransactionRequestData request = command.getTransactionRequest();
        AccountWrapper fromAccountWrapper = validateAndGetAccount(request, request.getFromAccountId(), TransactionTypeEnum.WITHDRAWAL);
        AccountWrapper toAccountWrapper = validateAndGetAccount(request, request.getToAccountId(), TransactionTypeEnum.DEPOSIT);
        LocalDateTime transactionDate = getNow();
        //get txntype charges
        List<Charge> charges = getCharges(fromAccountWrapper.account.getIdentifier(), TransactionTypeEnum.ACCOUNT_TRANSFER);
        //todo: get subTxnType charges

        TransactionEntity txn = doWithdraw(request, fromAccountWrapper, charges, getNow(), request.getFromAccountId());
        TransactionEntity txn2 = doDeposit(request, toAccountWrapper, new ArrayList<>(), getNow(), request.getToAccountId());

        return TransactionResponseData.build(request.getRoutingCode(), request.getExternalId(),
                request.getRequestCode(), ActionState.ACCEPTED,
                null, txn.getIdentifier() +"_to_"+ txn2.getIdentifier(), transactionDate);
    }

    private TransactionEntity doDeposit(TransactionRequestData request, AccountWrapper accountWrapper,
                                        List<Charge> charges, LocalDateTime transactionDate, String accountId) {
        BigDecimal amount = request.getAmount().getAmount();

        TransactionEntity txn = createTransaction(request,TransactionTypeEnum.DEPOSIT, transactionDate, CREDIT, null, accountId);
        String debitAccountIdentifier = accountWrapper.productDefinition.getCashAccountIdentifier();
        /* if subtxn is provided and it has an account configured the do debit that account*/
        if(StringUtils.isNotBlank(request.getSubTxnId())){
            Optional<SubTransactionType> subTxnTypeOpt = this.subTxnTypesService.findByIdentifier(request.getSubTxnId());
            if(subTxnTypeOpt.isPresent()) {
                txn.setSubTxnType(subTxnTypeOpt.get().getIdentifier());
                if (subTxnTypeOpt.get().getLedgerAccount() != null) {
                    debitAccountIdentifier = subTxnTypeOpt.get().getLedgerAccount();
                }
            }
        }
        final JournalEntry journalEntry = createJournalEntry(txn.getIdentifier(), TransactionTypeEnum.DEPOSIT.getCode(),
                DateConverter.toIsoString(transactionDate), request.getNote(), getLoginUser());

        HashSet<Debtor> debtors = new HashSet<>(1);
        HashSet<Creditor> creditors = new HashSet<>(1);

        addCreditor(accountWrapper.account.getIdentifier(), amount.doubleValue(), creditors);
        addDebtor(debitAccountIdentifier, amount.doubleValue(), debtors);


        prepareCharges(request, accountWrapper, charges, debtors, creditors, txn, accountId);

        if (debtors.isEmpty()) // must be same size as creditors
            throw ServiceException.badRequest("Debit and Credit doesn't match");

        journalEntry.setDebtors(debtors);
        journalEntry.setCreditors(creditors);

        transactionRepository.save(txn);

        ledgerManager.createJournalEntry(journalEntry);
        return txn;
    }


    private TransactionEntity doWithdraw(@NotNull TransactionRequestData request, @NotNull AccountWrapper accountWrapper,
                                 List<Charge> charges, LocalDateTime transactionDate, String accountId) {
        BigDecimal amount = request.getAmount().getAmount();

        TransactionEntity txn = createTransaction(request, TransactionTypeEnum.WITHDRAWAL, transactionDate, DEBIT, null, accountId);

        String creditAccountIdentifier = accountWrapper.productDefinition.getCashAccountIdentifier();
        /* if subtxn is provided and it has an account configured the do credit that account*/
        if(StringUtils.isNotBlank(request.getSubTxnId())){
            Optional<SubTransactionType> subTxnTypeOpt = this.subTxnTypesService.findByIdentifier(request.getSubTxnId());
            if(subTxnTypeOpt.isPresent()) {
                txn.setSubTxnType(subTxnTypeOpt.get().getIdentifier());
                if (subTxnTypeOpt.get().getLedgerAccount() != null) {
                    creditAccountIdentifier = subTxnTypeOpt.get().getLedgerAccount();
                }
            }
        }
        final JournalEntry journalEntry = createJournalEntry(txn.getIdentifier(), TransactionTypeEnum.WITHDRAWAL.getCode(),
                DateConverter.toIsoString(transactionDate), request.getNote(), getLoginUser());

        HashSet<Debtor> debtors = new HashSet<>(1);
        HashSet<Creditor> creditors = new HashSet<>(1);

        addCreditor(creditAccountIdentifier, amount.doubleValue(), creditors);
        addDebtor(accountWrapper.account.getIdentifier(), amount.doubleValue(), debtors);

        prepareCharges(request, accountWrapper, charges, debtors, creditors, txn, accountId);

        if (debtors.isEmpty()) // must be same size as creditors
            throw ServiceException.badRequest("Debit and Credit doesn't match");

        journalEntry.setDebtors(debtors);
        journalEntry.setCreditors(creditors);
        transactionRepository.save(txn);
        ledgerManager.createJournalEntry(journalEntry);
        return txn;
    }



    private void prepareCharges(@NotNull TransactionRequestData request, @NotNull AccountWrapper accountWrapper,
                                @NotNull List<Charge> charges, HashSet<Debtor> debtors, HashSet<Creditor> creditors,
                                TransactionEntity txn, String accountId) {


        BigDecimal amount = request.getAmount().getAmount();
        Currency currency = accountWrapper.productDefinition.getCurrency();

        BigDecimal total = MathUtil.normalize(calcTotalCharges(charges, amount), currency);
        if (MathUtil.isEmpty(total)) {
            return;
        }
        txn.setFeeAmount(total);

        if (creditors == null) {
            creditors = new HashSet<>(1);
        }
        if (debtors == null) {
            debtors = new HashSet<>(charges.size());
        }
        for(Charge charge : charges){
            addCreditor(charge.getIncomeAccountIdentifier(), calcChargeAmount(amount, charge).doubleValue(), creditors);
            addDebtor(accountWrapper.account.getIdentifier(), calcChargeAmount(amount, charge).doubleValue(), debtors);
            createTransaction(request,TransactionTypeEnum.CHARGES_PAYMENT, getNow(), DEBIT, txn, accountId);
        }

    }


    private AccountWrapper validateAndGetAccount(@NotNull TransactionRequestData request, String accountId, TransactionTypeEnum txnType) {
        //TODO: error handling
        Account account = ledgerManager.findAccount(accountId);
        validateAccount(request.getAmount(), account);

        ProductInstance product = productInstanceService.findByAccountIdentifier(accountId).get();
        ProductDefinition productDefinition = productDefinitionService.findProductDefinition(product.getProductIdentifier()).get();

        Currency currency = productDefinition.getCurrency();
        if (!currency.getCode().equals(request.getAmount().getCurrency()))
            throw new UnsupportedOperationException();

        request.normalizeAmounts(currency);

        Double withdrawableBalance = getWithdrawableBalance(account, productDefinition);
        if (txnType == TransactionTypeEnum.WITHDRAWAL && withdrawableBalance < request.getAmount().getAmount().doubleValue())
            throw new UnsupportedOperationException();

        return new AccountWrapper(account, product, productDefinition, withdrawableBalance);
    }

    Double getWithdrawableBalance(Account account, ProductDefinition productDefinition) {
        // on-hold amount, if any, is subtracted to payable account
        return MathUtil.subtractToZero(account.getBalance(), productDefinition.getMinimumBalance());
    }


    private void validateAccount(MoneyData requestAmount, Account account) {
        validateAccount(account);

        String accountId = account.getIdentifier();

        if (account.getHolders() != null) { // customer account
            ProductInstance product = productInstanceService.findByAccountIdentifier(accountId).get();
            ProductDefinition productDefinition = productDefinitionService.findProductDefinition(product.getProductIdentifier()).get();
            if (!Boolean.TRUE.equals(productDefinition.getActive()))
                throw new UnsupportedOperationException("Product Definition is inactive");

            Currency currency = productDefinition.getCurrency();
            if (!currency.getCode().equals(requestAmount.getCurrency()))
                throw new UnsupportedOperationException();
        }
    }

    private void validateAccount(Account account) {
        if (account == null)
            throw new UnsupportedOperationException("Account not found");
        if (!account.getState().equals(Account.State.OPEN.name()))
            throw new UnsupportedOperationException("Account is in state " + account.getState());
    }

    public List<Charge> getCharges(String accountIdentifier, TransactionTypeEnum transactionType) {
        List<Action> actions = actionService.fetchActions();

        List<String> actionIds = actions
                .stream()
                .filter(action -> action.getTransactionType().equals(transactionType.getCode()))
                .map(Action::getIdentifier)
                .collect(Collectors.toList());

        ProductInstance product = productInstanceService.findByAccountIdentifier(accountIdentifier).get();
        ProductDefinition productDefinition = productDefinitionService.findProductDefinition(product.getProductIdentifier()).get();

        return productDefinition.getCharges()
                .stream()
                .filter(charge -> actionIds.contains(charge.getActionIdentifier()))
                .collect(Collectors.toList());
    }
    // Util


    private LocalDateTime getNow() {
        return LocalDateTime.now(Clock.systemUTC());
    }
    private String getLoginUser() {
        return UserContextHolder.checkedGetUser();
    }


    private JournalEntry createJournalEntry(String actionIdentifier, String transactionType, String transactionDate, String message, String loginUser) {
        final JournalEntry journalEntry = new JournalEntry();
        journalEntry.setTransactionIdentifier(actionIdentifier);
        journalEntry.setTransactionType(transactionType);
        journalEntry.setTransactionDate(transactionDate);
        journalEntry.setMessage(message);
        journalEntry.setClerk(loginUser);
        return journalEntry;
    }

    private void addCreditor(String accountNumber, double amount, HashSet<Creditor> creditors) {
        Creditor creditor = new Creditor();
        creditor.setAccountNumber(accountNumber);
        creditor.setAmount(Double.toString(amount));
        creditors.add(creditor);
    }

    private void addDebtor(String accountNumber, double amount, HashSet<Debtor> debtors) {
        Debtor debtor = new Debtor();
        debtor.setAccountNumber(accountNumber);
        debtor.setAmount(Double.toString(amount));
        debtors.add(debtor);
    }

    private BigDecimal calcChargeAmount(BigDecimal amount, Charge charge) {
        return calcChargeAmount(amount, charge, null, false);
    }

    private BigDecimal calcChargeAmount(@NotNull BigDecimal amount, @NotNull Charge charge, Currency currency, boolean norm) {
        Double value = charge.getAmount();
        if (value == null)
            return null;

        BigDecimal portion = BigDecimal.valueOf(100.00d);
        MathContext mc = MathUtil.CALCULATION_MATH_CONTEXT;
        BigDecimal feeAmount = BigDecimal.valueOf(MathUtil.nullToZero(charge.getAmount()));
        BigDecimal result = charge.getProportional()
                ? amount.multiply(feeAmount.divide(portion, mc), mc)
                : feeAmount;
        return norm ? MathUtil.normalize(result, currency) : result;
    }

    @NotNull
    private BigDecimal calcTotalCharges(@NotNull List<Charge> charges, BigDecimal amount) {
        return charges.stream().map(charge -> calcChargeAmount(amount, charge)).reduce(MathUtil::add).orElse(BigDecimal.ZERO);
    }


    private TransactionEntity createTransaction(TransactionRequestData request, TransactionTypeEnum txnType,
                                                LocalDateTime transactionDate, String tranType,
                                                TransactionEntity parent, String accountId) {
        TransactionEntity txn = new TransactionEntity();
        UUID uuid=UUID.randomUUID();

        while(transactionRepository.findByIdentifier(uuid.toString()).isPresent()){
            uuid=UUID.randomUUID();
        }

        txn.setIdentifier(uuid.toString());
        txn.setRoutingCode(request.getRoutingCode());
        txn.setExternalId(request.getExternalId());
        txn.setTransactionType(txnType);
        txn.setAmount(request.getAmount().getAmount());
        //txn.setFeeAmount();
        txn.setState(ActionState.ACCEPTED);
        //txn.setCustomerAccountIdentifier();
        txn.setTransactionDate(transactionDate);
        txn.setExpirationDate(request.getExpiration());
        txn.setCreatedBy(getLoginUser());
        txn.setCreatedOn(getNow());
        /*txn.setLastModifiedBy();
        txn.setLastModifiedOn();*/
        markLastTransaction(accountId, transactionDate);
        txn.setAccountId(accountId);
        txn.setType(tranType);
        txn.setParentTransaction(parent);
        transactionRepository.save(txn);
        return txn;
    }

    private void markLastTransaction(final String productInstanceIdentifier, LocalDateTime transactionDate) {
        final Optional<ProductInstanceEntity> optionalProductInstance =
                this.productInstanceRepository.findByAccountIdentifier(productInstanceIdentifier);

        final ProductInstanceEntity productInstanceEntity = optionalProductInstance.orElseThrow(() ->
                ServiceException.notFound("Product instance {0} not found.", productInstanceIdentifier));

        productInstanceEntity.setLastTransactionDate(transactionDate);

        this.productInstanceRepository.save(productInstanceEntity);

    }
    public List<StatementResponse> fetchStatement(String accountId,
                                                  LocalDateTime fromDateTime,
                                                  LocalDateTime toDateTime) {
        return transactionRepository.findByAccountIdAndTransactionDateBetween(accountId, fromDateTime, toDateTime)
                .stream().map(txn -> {
                    StatementResponse statementObj = new StatementResponse();
                    statementObj.setTransactionCode(txn.getIdentifier());
                    statementObj.setTranType(txn.getTransactionType().name());
                    statementObj.setAmount(txn.getAmount());
                    statementObj.setTransactionDate(txn.getTransactionDate());
                    statementObj.setSubTxnType(txn.getSubTxnType());
                    statementObj.setType(txn.getType());
                    statementObj.setDescription(txn.getDescription());
                    return statementObj;
                }).collect(Collectors.toList());
    }


    public static class AccountWrapper {
        @NotNull
        private final Account account;
        @NotNull
        private final ProductInstance product;
        @NotNull
        private final ProductDefinition productDefinition;
        @NotNull
        private final Double withdrawableBalance;

        public AccountWrapper(Account account, ProductInstance product, ProductDefinition productDefinition, Double withdrawableBalance) {
            this.account = account;
            this.product = product;
            this.productDefinition = productDefinition;
            this.withdrawableBalance = withdrawableBalance;
        }
    }
}
