package org.mifosplatform.integrationtests;

import static org.junit.Assert.assertEquals;

import java.util.HashMap;
import java.util.List;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.mifosplatform.accounting.common.AccountingConstants.FINANCIAL_ACTIVITY;
import org.mifosplatform.accounting.financialactivityaccount.exception.DuplicateFinancialActivityAccountFoundException;
import org.mifosplatform.accounting.financialactivityaccount.exception.FinancialActivityAccountInvalidException;
import org.mifosplatform.integrationtests.common.CommonConstants;
import org.mifosplatform.integrationtests.common.Utils;
import org.mifosplatform.integrationtests.common.accounting.Account;
import org.mifosplatform.integrationtests.common.accounting.AccountHelper;
import org.mifosplatform.integrationtests.common.accounting.FinancialActivityAccountHelper;

import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;

@SuppressWarnings("rawtypes")
public class FinancialActivityAccountsTest {

    private ResponseSpecification responseSpec;
    private ResponseSpecification responseSpecForValidationError;
    private ResponseSpecification responseSpecForResourceNotFoundError;
    private RequestSpecification requestSpec;
    private AccountHelper accountHelper;
    private FinancialActivityAccountHelper financialActivityAccountHelper;
    // private final Integer assetTransferFinancialActivityId =
    // FINANCIAL_ACTIVITY.ASSET_TRANSFER.getValue();
    public static final Integer liabilityTransferFinancialActivityId = FINANCIAL_ACTIVITY.LIABILITY_TRANSFER.getValue();

    @Before
    public void setup() {
        Utils.initializeRESTAssured();
        this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
        this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
        this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
        this.responseSpecForValidationError = new ResponseSpecBuilder().expectStatusCode(400).build();
        this.responseSpecForResourceNotFoundError = new ResponseSpecBuilder().expectStatusCode(404).build();
        this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
        this.financialActivityAccountHelper = new FinancialActivityAccountHelper(this.requestSpec);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testFinancialActivityAccounts() {

        /** Create a Liability and an Asset Transfer Account **/
        Account liabilityTransferAccount = accountHelper.createLiabilityAccount();
        Account assetTransferAccount = accountHelper.createAssetAccount();
        Assert.assertNotNull(assetTransferAccount);
        Assert.assertNotNull(liabilityTransferAccount);

        /*** Create A Financial Activity to Account Mapping **/
        Integer financialActivityAccountId = (Integer) financialActivityAccountHelper.createFinancialActivityAccount(
                liabilityTransferFinancialActivityId, liabilityTransferAccount.getAccountID(), responseSpec,
                CommonConstants.RESPONSE_RESOURCE_ID);
        Assert.assertNotNull(financialActivityAccountId);

        /***
         * Fetch Created Financial Activity to Account Mapping and validate
         * created values
         **/
        assertFinancialActivityAccountCreation(financialActivityAccountId, liabilityTransferFinancialActivityId, liabilityTransferAccount);

        /**
         * Update Existing Financial Activity to Account Mapping and assert
         * changes
         **/
        Account newLiabilityTransferAccount = accountHelper.createLiabilityAccount();
        Assert.assertNotNull(newLiabilityTransferAccount);

        HashMap changes = (HashMap) financialActivityAccountHelper.updateFinancialActivityAccount(financialActivityAccountId,
                liabilityTransferFinancialActivityId, newLiabilityTransferAccount.getAccountID(), responseSpec,
                CommonConstants.RESPONSE_CHANGES);
        Assert.assertEquals(newLiabilityTransferAccount.getAccountID(), changes.get("glAccountId"));

        /** Validate update works correctly **/
        assertFinancialActivityAccountCreation(financialActivityAccountId, liabilityTransferFinancialActivityId,
                newLiabilityTransferAccount);

        /** Update with Invalid Financial Activity should fail **/
        List<HashMap> invalidFinancialActivityUpdateError = (List<HashMap>) financialActivityAccountHelper.updateFinancialActivityAccount(
                financialActivityAccountId, 232, newLiabilityTransferAccount.getAccountID(), responseSpecForValidationError,
                CommonConstants.RESPONSE_ERROR);
        assertEquals("validation.msg.financialactivityaccount.financialActivityId.is.not.one.of.expected.enumerations",
                invalidFinancialActivityUpdateError.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));

        /** Creating Duplicate Financial Activity should fail **/
        List<HashMap> duplicateFinancialActivityAccountError = (List<HashMap>) financialActivityAccountHelper
                .createFinancialActivityAccount(financialActivityAccountId, liabilityTransferAccount.getAccountID(), responseSpec,
                        CommonConstants.RESPONSE_ERROR);
        assertEquals(DuplicateFinancialActivityAccountFoundException.getErrorcode(),
                duplicateFinancialActivityAccountError.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));

        /**
         * Associating incorrect GL account types with a financial activity
         * should fail
         **/
        List<HashMap> invalidFinancialActivityAccountError = (List<HashMap>) financialActivityAccountHelper.updateFinancialActivityAccount(
                financialActivityAccountId, liabilityTransferFinancialActivityId, newLiabilityTransferAccount.getAccountID(), responseSpec,
                CommonConstants.RESPONSE_ERROR);
        assertEquals(FinancialActivityAccountInvalidException.getErrorcode(),
                invalidFinancialActivityAccountError.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));

        /** Should be able to delete a Financial Activity to Account Mapping **/
        Integer deletedFinancialActivityAccountId = financialActivityAccountHelper.deleteFinancialActivityAccount(
                financialActivityAccountId, responseSpec, CommonConstants.RESPONSE_RESOURCE_ID);
        Assert.assertNotNull(deletedFinancialActivityAccountId);
        Assert.assertEquals(financialActivityAccountId, deletedFinancialActivityAccountId);

        /*** Trying to fetch a Deleted Account Mapping should give me a 404 **/
        financialActivityAccountHelper.getFinancialActivityAccount(deletedFinancialActivityAccountId, responseSpecForResourceNotFoundError);
    }

    private void assertFinancialActivityAccountCreation(Integer financialActivityAccountId, Integer financialActivityId, Account glAccount) {
        HashMap mappingDetails = financialActivityAccountHelper.getFinancialActivityAccount(financialActivityAccountId, responseSpec);
        Assert.assertEquals(financialActivityId, ((HashMap) mappingDetails.get("financialActivityData")).get("id"));
        Assert.assertEquals(glAccount.getAccountID(), ((HashMap) mappingDetails.get("glAccountData")).get("id"));
    }
}

@@ -1374,24 +1374,94 @@
 ationError;%0A
+    private ResponseSpecification responseSpecForDomainRuleViolation;%0A
     private 
@@ -2394,32 +2394,139 @@
 e(400).build();%0A
+        this.responseSpecForDomainRuleViolation = new ResponseSpecBuilder().expectStatusCode(403).build();%0A
         this.res
@@ -5604,33 +5604,50 @@
 ActivityAccount(
-f
+liabilityTransferF
 inancialActivity
@@ -5638,39 +5638,32 @@
 inancialActivity
-Account
 Id, liabilityTra
@@ -5686,38 +5686,24 @@
 AccountID(),
- responseSpec,
 %0A           
@@ -5706,32 +5706,68 @@
                 
+ responseSpecForDomainRuleViolation,
  CommonConstants
@@ -6368,38 +6368,24 @@
 AccountID(),
- responseSpec,
 %0A           
@@ -6380,32 +6380,68 @@
 %0A               
+ responseSpecForDomainRuleViolation,
  CommonConstants

fix validations for financial activity accounts test