package com.fitbank.migrationdb.view;

import java.sql.Date;
import java.util.Calendar;

import com.fitbank.balance.helper.BalanceData;
import com.fitbank.balance.helper.BalanceList;
import com.fitbank.balance.helper.TransactionBalance;
import com.fitbank.common.ApplicationDates;
import com.fitbank.common.Helper;
import com.fitbank.common.RequestData;
import com.fitbank.common.conectivity.HbSession;
import com.fitbank.common.helper.Dates;
import com.fitbank.common.logger.FitbankLogger;
import com.fitbank.dto.GeneralRequest;
import com.fitbank.dto.financial.FinancialRequest;
import com.fitbank.dto.management.Detail;
import com.fitbank.dto.management.Field;
import com.fitbank.fin.common.provision.GeneralProvision;
import com.fitbank.fin.helper.TransactionData;
import com.fitbank.fin.helper.TransactionHelper;
import com.fitbank.hb.persistence.acco.Taccount;
import com.fitbank.hb.persistence.acco.view.Tprocessdateaccount;
import com.fitbank.hb.persistence.fin.Tbalance;
import com.fitbank.migrationdb.common.MonitorThreads;
import com.fitbank.view.acco.AccountBalances;

public class Provision extends Thread {

    private Taccount taccount;
    private MonitorThreads mh;

    private Detail detail;

    public Provision(GeneralRequest pGeneralRequest, Taccount pTaccount,
            MonitorThreads pMh) throws Exception {
        detail = (Detail) pGeneralRequest;
        taccount = pTaccount;
        mh = pMh;
    }

    public void run() {
        try {
            Helper.setSession(HbSession.getInstance().openSession());
            this.procesar();
        } catch (Exception e) {
            FitbankLogger.getLogger().error(e.getMessage());
        } finally {
            try {
                mh.removeCounter();
            } catch (Exception e) {
                FitbankLogger.getLogger().error(e.getMessage());
            }
        }
    }

    private void procesar() throws Exception {
        Helper.beginTransaction();
        FitbankLogger.getLogger().error(
                "Cuenta : " + taccount.getPk().getCcuenta());
        detail.addField(new Field("ACCOUNTINGVALIDATOR"));
        RequestData.setSession(detail);
        fillThreadLocal();
        try {
            FinancialRequest financialRequest = detail.toFinancialRequest();
            Tprocessdateaccount tprocessdateaccount = TransactionHelper
                    .getTransactionData().getTprocessdateaccount(
                            taccount.getPk().getCcuenta(),
                            taccount.getPk().getCpersona_compania());
            Date valuedate = tprocessdateaccount.getFcapitalizacion();
            if (valuedate != null) {
                try {
                    this.provision(financialRequest, valuedate);
                } catch (Exception e) {
                    FitbankLogger.getLogger().error(e.getMessage());
                }
            }
            Helper.commitTransaction();
        } finally {
            cleanThreadLocal();
        }
    }

    /**
     * Calcula provisiones para una cuenta.
     * 
     * @param pGeneralRequest
     * @param pValuedate
     *            Fecha desde la cual se calcula el interes, es la fecha de
     *            capitalizacion o corte mas un día.
     * @throws Exception
     */
    public void provision(FinancialRequest pGeneralRequest, Date pValuedate)
            throws Exception {
        Dates d = new Dates(pValuedate);
        d.addField(Calendar.DAY_OF_YEAR, 1);
        AccountBalances ab = new AccountBalances(taccount,
                ApplicationDates.DEFAULT_EXPIRY_DATE);
        if (ab == null || ab.getTbalances() == null) {
            return;
        }
        BalanceList<Tbalance> lbalance = ab.getTbalances()
                .getProvisionBalance();
        if (lbalance.size() > 0) {
            FinancialRequest freq = pGeneralRequest;
            freq.setAccountingDate(pValuedate);
            freq.setProcessdate(pValuedate);
            freq.setValuedate(pValuedate);
            if (TransactionHelper.getTransactionData()
                    .getFinancialTransaction() != null) {
                TransactionHelper.getTransactionData()
                        .getFinancialTransaction().getFinancialRequest()
                        .setValuedate(pValuedate);
                TransactionHelper.getTransactionData()
                        .getFinancialTransaction().getFinancialRequest()
                        .setAccountingDate(freq.getAccountingDate());
                TransactionHelper.getTransactionData()
                        .getFinancialTransaction().getFinancialRequest()
                        .setProcessdate(freq.getProcessdate());
            }
            TransactionHelper.getTransactionData()
                    .setAccountingdate(pValuedate);
            new GeneralProvision(lbalance, freq, true);
            TransactionHelper.getTransactionData().getFinancialTransaction()
                    .getFinancialRequest().setValuedate(d.getDate());
            TransactionHelper.getTransactionData().getFinancialTransaction()
                    .saveProvisionBalances();
            TransactionHelper.getTransactionData().getFinancialTransaction()
                    .setProcessDateAccount();
            TransactionHelper.getTransactionData().getFinancialTransaction()
                    .saveAccountData();
        }
        Helper.flushTransaction();
    }

    public void cleanThreadLocal() throws Exception {
        TransactionHelper.getTransactionData().clean();
        TransactionBalance.getBalanceData().clean();
    }

    public void fillThreadLocal() throws Exception {
        TransactionData transactionData = new TransactionData();
        BalanceData balanceData = new BalanceData();
        TransactionHelper.setTransactionData(transactionData);
        TransactionBalance.setBalanceData(balanceData);
    }

}
