package me.teridax.jcash.gui.transfer;

import me.teridax.jcash.Logging;
import me.teridax.jcash.banking.management.BankingManagementSystem;
import me.teridax.jcash.decode.StringDecoder;

public class TransferData {

    private final BankingManagementSystem bms;

    public TransferData(BankingManagementSystem bms) {
        this.bms = bms;
    }

    /**
     * Transfers a certain amount of money to the specified account of the specified bank
     *
     * @param amount     the amount to transfer
     * @param blz        the bank that manages the account
     * @param ibanString the internal bank account number to transfer money to
     * @throws IllegalArgumentException if the bank or the account do not exist
     */
    public void transferValue(double amount, String blz, String ibanString) throws IllegalArgumentException {
        // get bank to transfer to
        var bank = bms.getBank(blz);
        if (bank.isEmpty()) {
            Logging.LOGGER.warning("Bank not found: " + blz);
            throw new IllegalArgumentException("Bank not found: " + blz);
        }

        // validate iban of target account
        var iban = 0;
        try {
            iban = StringDecoder.decodeUniqueIdentificationNumber(ibanString);
        } catch (Exception ex) {
            Logging.LOGGER.warning("IBAN has invalid format: " + ibanString + " because: " + ex.getMessage());
            throw new IllegalArgumentException("IBAN has invalid format: " + ibanString);
        }

        // get account to transfer value to
        var account = bank.get().getAccount(iban);
        if (account.isEmpty()) {
            Logging.LOGGER.warning("Account not found: " + iban);
            throw new IllegalArgumentException("Account not found: " + iban);
        }

        account.get().getPrimaryAccount().deposit(amount);
    }

    /**
     * Validates the given BLZ. If no bank with the given BLZ can be found
     * this method returns false. Otherwise, true is returned.
     * @param blz the BLZ to validate
     * @return true if the BLZ is valid and false otherwise
     */
    public boolean validateBLZ(String blz) {
        return bms.getBank(blz).isPresent();
    }

    /**
     * Validates the given IBAN for the given BLZ. This method assumes the BLZ to be valid.
     * If this is not the case, this function will throw an exception.
     * Returns true if an account with the given IBAN was found for bank of the given BLZ.
     * @param blz bank to search in
     * @param ibanString account to search for
     * @return true if the account was found false otherwise
     */
    public boolean validateIBAN(String blz, String ibanString) {
        var bank = bms.getBank(blz);
        try {
            var iban = StringDecoder.decodeUniqueIdentificationNumber(ibanString);
            return bank.map(value -> value.getAccount(iban).isPresent()).orElse(false);
        } catch (Exception e) {
            return false;
        }
    }
}
