package app

import (
	"fmt"
	"time"

	"code.tnxs.net/taxnexus/lib/api/geo/geo_client/tax_type"
)

var exciseCategories = map[string]string{
	"cannabis-excise": "cannabis-excise",
	"telecom-excise":  "telecom-excise",
}

var cannabisCategories = map[string]string{
	"cannabis-ag":    "cannabis-ag",
	"cannabis-trade": "cannabis-trade",
}

var merchCategories = map[string]string{
	"cannabis-retail": "cannabis-retail",
	"sales-district":  "sales-district",
	"sales-state":     "sales-state",
}

var telecomCategories = map[string]string{
	"broadband":          "broadband",
	"voip-interstate":    "voip-interstate",
	"voip-international": "voip-international",
	"voip-intrastate":    "voip-intrastate",
	"voip":               "voip",
	"wireless":           "wireless",
}

// GetTaxType is first class retrieval function
func GetTaxType(recordID string, principal *User) *TaxType {
	obj, ok := taxTypeCache.get(recordID)
	if ok {
		return obj
	}
	obj, err := GetTaxTypeByID(recordID, principal)
	if err != nil {
		return &TaxType{}
	}
	return obj
}

// GetTaxTypeByID is first class retrieval function
func GetTaxTypeByID(recordID string, principal *User) (*TaxType, error) {
	sugar.Debugf("render.GetTaxTypesByID: 📥")
	if recordID == "" {
		return nil, fmt.Errorf("render.getTaxTypeByID: 💣 ⛔ key is blank")
	}
	obj, ok := taxTypeCache.get(recordID)
	if ok {
		sugar.Debugf("render.getTaxTypeByID: 👍 🎯 📤")
		return obj, nil
	}
	geoParams := tax_type.NewGetTaxTypesParamsWithTimeout(getTimeout)
	geoParams.TaxTypeID = &recordID
	response, err := geoClient.TaxType.GetTaxTypes(geoParams, principal.Auth)
	if err != nil {
		return nil, err
	}
	var newObj *TaxType
	for _, itm := range response.Payload.Data { // single iteration execution
		newObj = UnMarshalTaxType(itm)
	}
	taxTypeCache.put(recordID, newObj)
	sugar.Debugf("render.getTaxTypeByID: 👍 🆕 📤")
	return newObj, nil
}

// GetCannabisTaxTypes is first class retrieval function
func GetCannabisTaxTypes(taxTypes []*TaxType) []*TaxType {
	objList := []*TaxType{}
	for _, tt := range taxTypes {
		if tt != nil {
			if inMap(cannabisCategories, tt.Category) && isActive(tt) {
				sugar.Debugf("render.getCannabisTaxTypes: ➡ ✅ cannabis %s", tt.Name)
				objList = append(objList, tt)
			}
		}
	}
	if len(objList) == 0 {
		return nil
	}
	return objList
}

// GetExciseTaxTypes is first class retrieval function
func GetExciseTaxTypes(taxTypes []*TaxType) []*TaxType {
	objList := []*TaxType{}
	for _, tt := range taxTypes {
		if tt != nil {
			if inMap(exciseCategories, tt.Category) && isActive(tt) {
				sugar.Debugf("render.getExciseTaxTypes: ➡ ✅ excise %s", tt.Name)
				objList = append(objList, tt)
			}
		}
	}
	if len(objList) == 0 {
		return nil
	}
	return objList
}

// GetBusinessTaxTypes is first class retrieval function
func GetBusinessTaxTypes(taxTypes []*TaxType) []*TaxType {
	objList := []*TaxType{}
	for _, tt := range taxTypes {
		if tt != nil {
			if tt.Category == "business" && isActive(tt) {
				sugar.Debugf("render.getBusinessTaxTypes: ➡ ✅ business %s", tt.Name)
				objList = append(objList, tt)
			}
		}
	}
	if len(objList) == 0 {
		return nil
	}
	return objList
}

// GetMerchTaxTypes is first class retrieval function
func GetMerchTaxTypes(taxTypes []*TaxType) []*TaxType {
	objList := []*TaxType{}
	for _, tt := range taxTypes {
		if tt != nil {
			if inMap(merchCategories, tt.Category) && isActive(tt) {
				sugar.Debugf("render.getMerchTaxTypes: ➡ ✅ merch %s", tt.Name)
				objList = append(objList, tt)
			}
		}
	}
	if len(objList) == 0 {
		return nil
	}
	return objList
}

// GetTelecomTaxTypes is first class retrieval function
func GetTelecomTaxTypes(taxTypes []*TaxType) []*TaxType {
	objList := []*TaxType{}
	for _, tt := range taxTypes {
		if tt != nil {
			if inMap(telecomCategories, tt.Category) && isActive(tt) {
				sugar.Debugf("render.getTelecomTaxTypes: ➡ ✅ telecom %s", tt.Name)
				objList = append(objList, tt)
			}
		}
	}
	if len(objList) == 0 {
		return nil
	}
	return objList
}

func inMap(values map[string]string, str string) bool {
	_, ok := values[str]
	return ok
}
func isActive(tt *TaxType) bool {
	if tt.EndDate.Time.IsZero() && tt.EffectiveDate.Time.Before(time.Now()) {
		return true
	}
	if tt.EndDate.Time.After(time.Now()) && tt.EffectiveDate.Time.Before(time.Now()) {
		return true
	}
	return false
}
