package mysql

import (
	"encoding/json"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
	resourcedomain "hyapp/services/wallet-service/internal/domain/resource"
	"sort"
	"strings"
)

func normalizeGiftConfigCommand(command resourcedomain.GiftConfigCommand) resourcedomain.GiftConfigCommand {
	command.GiftID = strings.TrimSpace(command.GiftID)
	command.Status = resourcedomain.NormalizeStatus(command.Status)
	command.Name = strings.TrimSpace(command.Name)
	command.PresentationJSON = normalizeJSONObject(command.PresentationJSON)
	command.CPRelationType = normalizeCPRelationType(command.CPRelationType)
	command.PriceVersion = strings.TrimSpace(command.PriceVersion)
	command.RegionIDs = normalizeRegionIDs(command.RegionIDs)
	command.GiftTypeCode = resourcedomain.NormalizeGiftTypeCode(command.GiftTypeCode)
	// 非 VIP 礼物不保留陈旧等级；类型切换后服务端主动归零，保证客户端只需按
	// gift_type_code + vip_level 解释目录，不会看到普通礼物携带误导性的等级。
	if !resourcedomain.IsVIPGiftType(command.GiftTypeCode) {
		command.VIPLevel = 0
	}
	command.ChargeAssetType = strings.ToUpper(strings.TrimSpace(command.ChargeAssetType))
	if command.ChargeAssetType == "" {
		command.ChargeAssetType = ledger.AssetCoin
	}
	command.EffectTypes = normalizeGiftEffectTypes(command.EffectTypes)

	command.GiftPointAmount = 0
	if command.EffectiveAtMS < 0 {
		command.EffectiveAtMS = 0
	}
	if command.EffectiveFromMS < 0 {
		command.EffectiveFromMS = 0
	}
	if command.EffectiveToMS < 0 {
		command.EffectiveToMS = 0
	}
	return command
}

func validateGiftConfigCommand(command resourcedomain.GiftConfigCommand) error {
	if command.GiftID == "" || command.ResourceID <= 0 || command.Name == "" || command.PriceVersion == "" {
		return xerr.New(xerr.InvalidArgument, "gift config command is incomplete")
	}
	if !resourcedomain.ValidStatus(command.Status) {
		return xerr.New(xerr.InvalidArgument, "status is invalid")
	}
	if command.CoinPrice < 0 || command.HeatValue < 0 {
		return xerr.New(xerr.InvalidArgument, "gift price is invalid")
	}
	if !resourcedomain.ValidGiftTypeCode(command.GiftTypeCode) {
		return xerr.New(xerr.InvalidArgument, "gift type is invalid")
	}
	if resourcedomain.IsVIPGiftType(command.GiftTypeCode) && command.VIPLevel <= 0 {
		return xerr.New(xerr.InvalidArgument, "vip gift level is required")
	}
	if command.CPRelationType != "" && command.GiftTypeCode != resourcedomain.GiftTypeCP {
		return xerr.New(xerr.InvalidArgument, "cp relation type requires cp gift type")
	}
	if !ledger.ValidGiftChargeAssetType(command.ChargeAssetType) {
		return xerr.New(xerr.InvalidArgument, "gift charge asset type is invalid")
	}
	if command.EffectiveFromMS > 0 && command.EffectiveToMS > 0 && command.EffectiveToMS <= command.EffectiveFromMS {
		return xerr.New(xerr.InvalidArgument, "gift effective time range is invalid")
	}
	for _, effectType := range command.EffectTypes {
		if !resourcedomain.ValidGiftEffectType(effectType) {
			return xerr.New(xerr.InvalidArgument, "gift effect type is invalid")
		}
	}
	if len(command.RegionIDs) == 0 {
		return xerr.New(xerr.InvalidArgument, "gift regions are required")
	}
	for _, regionID := range command.RegionIDs {
		if regionID < 0 {
			return xerr.New(xerr.InvalidArgument, "gift region is invalid")
		}
	}
	return nil
}

func normalizeGiftEffectTypes(values []string) []string {
	seen := make(map[string]struct{}, len(values))
	out := make([]string, 0, len(values))
	for _, value := range values {
		value = resourcedomain.NormalizeGiftEffectType(value)
		if value == "" {
			continue
		}
		if _, ok := seen[value]; ok {
			continue
		}
		seen[value] = struct{}{}
		out = append(out, value)
	}
	sort.Strings(out)
	return out
}

func cpRelationTypeFromPresentationJSON(value string) string {
	var payload map[string]any
	if err := json.Unmarshal([]byte(normalizeJSONObject(value)), &payload); err != nil {
		return ""
	}
	if raw, ok := payload["cp_relation_type"].(string); ok {
		return normalizeCPRelationType(raw)
	}
	return ""
}

func giftPresentationWithCPRelationType(value string, relationType string) string {
	relationType = normalizeCPRelationType(relationType)
	var payload map[string]any
	if err := json.Unmarshal([]byte(normalizeJSONObject(value)), &payload); err != nil || payload == nil {
		payload = map[string]any{}
	}

	if relationType == "" {
		delete(payload, "cp_relation_type")
	} else {
		payload["cp_relation_type"] = relationType
	}
	encoded, err := json.Marshal(payload)
	if err != nil {
		return "{}"
	}
	return string(encoded)
}

func normalizeCPRelationType(value string) string {
	switch strings.ToLower(strings.TrimSpace(value)) {
	case "cp":
		return "cp"
	case "brother":
		return "brother"
	case "sister":
		return "sister"
	default:
		return ""
	}
}
