package mapper

import (
	Dictionary "cf-experian/module_server/handlers/Dictionary"
	Schema "cf-experian/module_server/handlers/Schema"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	log "github.com/rs/zerolog/log"
)

func RunMapper(createBody Schema.CreateBody) Schema.CreditReport {

	var creditReport Schema.CreditReport

	totalEnquiry := 0
	totalEnquiry += createBody.Body.ProcessResponse.Out.INProfileResponse.TotalCAPS_Summary.TotalCAPSLast180Days
	totalEnquiry += createBody.Body.ProcessResponse.Out.INProfileResponse.NonCreditCAPS.NonCreditCAPS_Summary.NonCreditCAPSLast180Days

	log.Print("Mapper: MessageText")
	log.Print("createBody.ID")
	log.Print(createBody.ID)
	log.Print("createBody.PanValidation")
	log.Print(createBody.PanValidation)

	creditReport.ApplicationID = createBody.ID
	creditReport.Score = createBody.Body.ProcessResponse.Out.INProfileResponse.SCORE.BureauScore
	creditReport.NoOfActiveAccounts = createBody.Body.ProcessResponse.Out.INProfileResponse.CAIS_Account.CAIS_Summary.Credit_Account.CreditAccountActive
	creditReport.TotalPastDue = 0
	creditReport.Past12Months = totalEnquiry
	creditReport.Past24Months = totalEnquiry
	creditReport.TotalEnquiry = totalEnquiry
	creditReport.ZeroBalanceAccount = createBody.Body.ProcessResponse.Out.INProfileResponse.CAIS_Account.CAIS_Summary.Credit_Account.CreditAccountClosed
	creditReport.Applicant_type = createBody.ApplicantType
	creditReport.Created_at = getCurrentDate()
	creditReport.PanValidation = createBody.PanValidation
	creditReport.Bureau = "experian"

	activeCreditCardLimit := 0
	sanctionAmount := 0
	totalPastDueAmount := 0
	pastDueAccount := 0
	Date_of_birth := ""
	var AddressLists []Schema.CFAddressLists
	PanList := []string{}
	ContactList := []string{}
	VoterList := []string{}
	NationalList := []string{}

	for _, foirBucket := range createBody.Body.ProcessResponse.Out.INProfileResponse.CAIS_Account.CAIS_Account_DETAILS {
		var _foir Schema.Foir
		var __AddressLists Schema.CFAddressLists
		var Rate_of_Interest = "0"
		if len(foirBucket.Rate_of_Interest) > 0 {
			Rate_of_Interest = foirBucket.Rate_of_Interest
		}

		_foir.ApplicationID = createBody.ID
		_foir.CreditId = 1
		_foir.AccountType = strings.Title(strings.ToLower(Dictionary.AccountType[foirBucket.Account_Type]))
		_foir.Institution = foirBucket.Subscriber_Name
		_foir.OwnershipType = Dictionary.AccountHolderType[foirBucket.AccountHoldertypeCode]
		_foir.ApprovedAmount = foirBucket.Highest_Credit_or_Original_Loan_Amount
		_foir.Balance = foirBucket.Current_Balance
		_foir.InterestRate = Rate_of_Interest
		_foir.RepaymentTenure = foirBucket.Repayment_Tenure
		_foir.InstallmentAmount = foirBucket.Scheduled_Monthly_Payment_Amount
		_foir.DateOpened = getParsedDate(foirBucket.Open_Date)
		_foir.DateClosed = getParsedDate(foirBucket.Date_Closed)
		_foir.LastPaymentDate = getParsedDate(foirBucket.Date_of_Last_Payment)
		_foir.LastPayment = foirBucket.Value_of_Credits_Last_Month
		_foir.PastDueAmount = foirBucket.Amount_Past_Due
		_foir.DPD = getDPD(foirBucket.CAIS_Account_History)
		_foir.ApplicantType = createBody.ApplicantType
		_foir.CC_loan = 1
		_foir.IsOpened = 1
		_foir.CreatedBy = createBody.UserID
		_foir.CreatedAt = getCurrentDate()
		_foir.ReportedDate = getParsedDate(foirBucket.Date_Reported)

		totalPastDueAmount += foirBucket.Amount_Past_Due
		sanctionAmount += foirBucket.Highest_Credit_or_Original_Loan_Amount
		if len(Date_of_birth) == 0 {
			Date_of_birth = foirBucket.CAIS_Holder_Details.Date_of_birth
		}

		if _foir.AccountType == "Credit Card" {
			_foir.CC_loan = 0
			_foir.InstallmentAmount = foirBucket.Highest_Credit_or_Original_Loan_Amount
			activeCreditCardLimit += foirBucket.Highest_Credit_or_Original_Loan_Amount
		}

		if (Schema.CAIS_holder_Address_Details{} != foirBucket.CAIS_Holder_Address_Details) {
			__AddressLists.Address = fmt.Sprint(foirBucket.CAIS_Holder_Address_Details.First_Line_Of_Address_non_normalized, foirBucket.CAIS_Holder_Address_Details.Second_Line_Of_Address_non_normalized, foirBucket.CAIS_Holder_Address_Details.Third_Line_Of_Address_non_normalized)
			if len(__AddressLists.Address) > 0 {
				__AddressLists.State = foirBucket.CAIS_Holder_Address_Details.State_non_normalized
				__AddressLists.Postal = foirBucket.CAIS_Holder_Address_Details.ZIP_Postal_Code_non_normalized
				AddressLists = append(AddressLists, __AddressLists)
			}
		}

		if foirBucket.Amount_Past_Due > 0 {
			pastDueAccount++
		}

		if len(_foir.DateClosed) > 0 {
			_foir.IsOpened = 0
		}

		creditReport.Foir = append(creditReport.Foir, _foir)
	}

	if len(createBody.Body.ProcessResponse.Out.INProfileResponse.NonCreditCAPS.CAPS_Application_Details) > 0 {
		var _AddressLists Schema.CFAddressLists

		for _, applicationDetailsBucket := range createBody.Body.ProcessResponse.Out.INProfileResponse.CAPS.CAPS_Application_Details {
			_AddressLists.Address = fmt.Sprint(applicationDetailsBucket.CAPS_Applicant_Address_Details.FlatNoPlotNoHouseNo, applicationDetailsBucket.CAPS_Applicant_Address_Details.BldgNoSocietyName, applicationDetailsBucket.CAPS_Applicant_Address_Details.RoadNoNameAreaLocality, applicationDetailsBucket.CAPS_Applicant_Address_Details.Landmark, applicationDetailsBucket.CAPS_Applicant_Address_Details.City)
			_AddressLists.State = applicationDetailsBucket.CAPS_Applicant_Address_Details.State
			_AddressLists.Postal = applicationDetailsBucket.CAPS_Applicant_Address_Details.PINCode

			//PANIdsList
			if (Schema.CAPS_applicant_Details{} != applicationDetailsBucket.CAPS_Applicant_Details) {
				if contains(PanList, applicationDetailsBucket.CAPS_Applicant_Details.IncomeTaxPan) {
					PanList = append(PanList, strings.TrimSpace(applicationDetailsBucket.CAPS_Applicant_Details.IncomeTaxPan))
				}
				if contains(ContactList, applicationDetailsBucket.CAPS_Applicant_Details.MobilePhoneNumber) {
					ContactList = append(ContactList, strings.TrimSpace(applicationDetailsBucket.CAPS_Applicant_Details.MobilePhoneNumber))
				}
				if contains(VoterList, applicationDetailsBucket.CAPS_Applicant_Details.Voter_s_Identity_Card) {
					VoterList = append(VoterList, strings.TrimSpace(applicationDetailsBucket.CAPS_Applicant_Details.Voter_s_Identity_Card))
				}
				if contains(NationalList, applicationDetailsBucket.CAPS_Applicant_Details.Universal_ID_Number) {
					NationalList = append(NationalList, strings.TrimSpace(applicationDetailsBucket.CAPS_Applicant_Details.Universal_ID_Number))
				}
			}
		}

		AddressLists = append(AddressLists, _AddressLists)
	}

	creditReport.DateOfBirth = getParsedDate(Date_of_birth)
	creditReport.ActiveCreditCardLimit = activeCreditCardLimit
	creditReport.SanctionAmount = sanctionAmount
	creditReport.TotalPastDue = totalPastDueAmount
	creditReport.PastDueAccount = pastDueAccount
	creditReport.AddressInfoList = getStructToJsonString(AddressLists)
	creditReport.VoterID = getStructToJsonString(VoterList)
	creditReport.ContactInfoList = getStructToJsonString(ContactList)
	creditReport.PANIdsList = getStructToJsonString(PanList)
	creditReport.NationalIdsList = getStructToJsonString(NationalList)

	return creditReport
}

func contains(s []string, e string) bool {
	if len(e) == 0 {
		return false
	}

	for _, a := range s {
		if a == e {
			return false
		}
	}
	return true
}

func getStructToJsonString(lists interface{}) string {
	jsonLists, err := json.Marshal(lists)
	if err != nil {
		fmt.Printf("Error: %s", err.Error())
	}

	return string(jsonLists)
}

func getDPD(CAIS_Account_History []Schema.CAIS_account_History) string {

	DP_Due_string := ""
	zeroBucket, firstBucket, secondBucket, thirdBucket, fourBucket, fiveBucket, sixBucket, SETBucket, STDBucket, SUBBucket, DBTBucket, SMABucket, LSSBucket := 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	for _, accountHistory := range CAIS_Account_History {

		if len(accountHistory.Days_Past_Due) > 0 {
			DP_Due, err := strconv.Atoi(accountHistory.Days_Past_Due)
			if err != nil {
				log.Print(err)
				DP_Due_string = accountHistory.Days_Past_Due
			}
			if DP_Due > 1 && DP_Due <= 29 {
				zeroBucket++
			} else if DP_Due >= 30 && DP_Due <= 59 {
				firstBucket++
			} else if DP_Due >= 60 && DP_Due <= 89 {
				secondBucket++
			} else if DP_Due >= 90 && DP_Due <= 119 {
				thirdBucket++
			} else if DP_Due >= 120 && DP_Due <= 149 {
				fourBucket++
			} else if DP_Due >= 150 && DP_Due <= 179 {
				fiveBucket++
			} else if DP_Due >= 180 {
				sixBucket++
			} else if DP_Due_string == "S" {
				SETBucket++
			} else if DP_Due_string == "D" {
				DBTBucket++
			} else if DP_Due_string == "B" {
				SUBBucket++
			} else if DP_Due_string == "L" {
				LSSBucket++
			} else if DP_Due_string == "M" {
				SMABucket++
			}
		}
	}

	var DBase string = `{`
	var DHead string = `{`
	var DFoot string = `}`

	if zeroBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["0"] + `":` + strconv.Itoa(zeroBucket) + `,`
	}
	if firstBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["1"] + `":` + strconv.Itoa(firstBucket) + `,`
	}
	if secondBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["2"] + `":` + strconv.Itoa(secondBucket) + `,`
	}
	if thirdBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["3"] + `":` + strconv.Itoa(thirdBucket) + `,`
	}
	if fourBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["4"] + `":` + strconv.Itoa(fourBucket) + `,`
	}
	if fiveBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["5"] + `":` + strconv.Itoa(fiveBucket) + `,`
	}
	if sixBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["6"] + `":` + strconv.Itoa(sixBucket) + `,`
	}
	if STDBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["S"] + `":` + strconv.Itoa(STDBucket) + `,`
	}
	if SUBBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["B"] + `":` + strconv.Itoa(SUBBucket) + `,`
	}
	if DBTBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["D"] + `":` + strconv.Itoa(DBTBucket) + `,`
	}
	if SMABucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["M"] + `":` + strconv.Itoa(SMABucket) + `,`
	}
	if LSSBucket > 0 {
		DHead += `"` + Dictionary.PaymentStatus["L"] + `":` + strconv.Itoa(LSSBucket) + `,`
	}

	if DHead == DBase {
		DHead = "[]"
		DFoot = ""
	} else {
		DHead = strings.TrimRight(DHead, ",")
	}

	return string(DHead + DFoot)
}

func getCurrentDate() string {
	loc, _ := time.LoadLocation("Asia/Kolkata")
	now := time.Now().In(loc)
	return now.Format("2006-01-02 15:04:05")
}

func getParsedDate(s string) string {
	if len(s) > 0 {
		y := s[0:4]
		m := s[4:6]
		d := s[6:8]

		return fmt.Sprint(y, "-", m, "-", d)
	}
	return ""
}
