package repository

import (
	"sort"
	"strconv"

	"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	utils "gitlab.com/mbugroup/lti-api.git/internal/utils"
	approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
	"gorm.io/gorm"
)

type ConstantRepository interface {
	GetConstants() (map[string]interface{}, error)
}

type ConstantRepositoryImpl struct {
	*repository.BaseRepositoryImpl[entity.Constant]
}

func NewConstantRepository(db *gorm.DB) ConstantRepository {
	return &ConstantRepositoryImpl{
		BaseRepositoryImpl: repository.NewBaseRepository[entity.Constant](db),
	}
}

func (r *ConstantRepositoryImpl) GetConstants() (map[string]interface{}, error) {
	flagList := make([]string, 0)
	for f := range utils.AllFlagTypes() {
		flagList = append(flagList, string(f))
	}
	sort.Strings(flagList)

	productMainFlags := utils.ProductMainFlags()
	productMainFlagValues := make([]string, len(productMainFlags))
	for i, flag := range productMainFlags {
		productMainFlagValues[i] = string(flag)
	}

	type productFlagOption struct {
		Flag                string   `json:"flag"`
		SubFlags            []string `json:"sub_flags"`
		AllowWithoutSubFlag bool     `json:"allow_without_sub_flag"`
	}

	productOptions := utils.ProductFlagOptions()
	productFlagOptions := make([]productFlagOption, 0, len(productOptions))
	for _, option := range productOptions {
		subFlags := make([]string, len(option.SubFlags))
		for i, subFlag := range option.SubFlags {
			subFlags[i] = string(subFlag)
		}
		productFlagOptions = append(productFlagOptions, productFlagOption{
			Flag:                string(option.Flag),
			SubFlags:            subFlags,
			AllowWithoutSubFlag: option.AllowWithoutSubFlag,
		})
	}

	productSubFlagToFlagRaw := utils.ProductSubFlagToFlag()
	productSubFlagToFlag := make(map[string]string, len(productSubFlagToFlagRaw))
	for subFlag, flag := range productSubFlagToFlagRaw {
		productSubFlagToFlag[string(subFlag)] = string(flag)
	}

	legacyAliasesRaw := utils.LegacyFlagTypeAliases()
	legacyAliases := make(map[string]string, len(legacyAliasesRaw))
	for legacy, canonical := range legacyAliasesRaw {
		legacyAliases[string(legacy)] = string(canonical)
	}

	type approvalStepConstant struct {
		StepNumber uint16 `json:"step_number"`
		StepName   string `json:"step_name"`
	}

	workflowConstants := approvalutils.WorkflowConstants()
	workflowKeys := make([]string, 0, len(workflowConstants))
	for key := range workflowConstants {
		workflowKeys = append(workflowKeys, key)
	}
	sort.Strings(workflowKeys)

	approvalWorkflows := make([]map[string]interface{}, 0, len(workflowKeys))
	for _, key := range workflowKeys {
		stepMap := workflowConstants[key]
		if len(stepMap) == 0 {
			continue
		}

		stepList := make([]approvalStepConstant, 0, len(stepMap))
		for stepStr, label := range stepMap {
			stepNum, err := strconv.ParseUint(stepStr, 10, 16)
			if err != nil || stepNum == 0 {
				continue
			}
			stepList = append(stepList, approvalStepConstant{
				StepNumber: uint16(stepNum),
				StepName:   label,
			})
		}
		if len(stepList) == 0 {
			continue
		}
		sort.Slice(stepList, func(i, j int) bool {
			return stepList[i].StepNumber < stepList[j].StepNumber
		})

		approvalWorkflows = append(approvalWorkflows, map[string]interface{}{
			"key":   key,
			"steps": stepList,
		})
	}

	adjustmentSubtypesByType := utils.AdjustmentTransactionSubtypesByTypeForFrontend()

	return map[string]interface{}{
		"flags": flagList,
		"warehouse_types": []string{
			"AREA",
			"LOKASI",
			"KANDANG",
		},
		"stock_log": map[string][]string{
			"log_types":         []string{"TRANSFER", "ADJUSTMENT", "MARKETING", "CHICKIN", "PURCHASE", "RECORDING"},
			"transaction_types": []string{"INCREASE", "DECREASE"},
		},
		"supplier_categories": []string{
			"BOP",
			"SAPRONAK",
		},
		"customer_supplier_types": []string{
			"BISNIS",
			"INDIVIDUAL",
		},
			"adjustment": map[string]interface{}{
				"transaction_subtypes": adjustmentSubtypesByType,
			},
			"legacy_flag_aliases": legacyAliases,
			"product_flag_mapping": map[string]interface{}{
				"flags":            productMainFlagValues,
				"options":          productFlagOptions,
				"sub_flag_to_flag": productSubFlagToFlag,
			},
			"approval_workflows": approvalWorkflows,
		}, nil
}
