package commerce

import (
	"fmt"
	"strings"
)

func (s *Service) validatePluginCartFields(product Product, sliderValues map[string]any) error {
	if product.APIType != "plugin" {
		return nil
	}
	if product.APIIdentifier == nil || strings.TrimSpace(*product.APIIdentifier) == "" {
		return BadRequest("插件商品未绑定开通插件")
	}
	manifest := s.publicPluginForProduct(product)
	if manifest == nil {
		return BadRequest("插件商品未绑定开通插件")
	}
	page, _ := manifest["product_page"].(map[string]any)
	fields := asSlice(page["purchase_fields"])
	if len(fields) == 0 {
		return nil
	}
	values := map[string]any{}
	if sliderValues != nil {
		if raw, ok := sliderValues["__plugin_fields"].(map[string]any); ok {
			values = raw
		}
	}
	var missing []string
	var invalid []string
	for _, item := range fields {
		field, ok := item.(map[string]any)
		if !ok {
			continue
		}
		key := strings.TrimSpace(fmt.Sprint(field["key"]))
		if key == "" || key == "<nil>" {
			continue
		}
		label := strings.TrimSpace(fmt.Sprint(field["label"]))
		if label == "" || label == "<nil>" {
			label = key
		}
		value := values[key]
		if truthy(field["required"]) && !present(value) {
			missing = append(missing, label)
			continue
		}
		if !present(value) {
			continue
		}
		if fmt.Sprint(field["type"]) == "select" {
			allowed := map[string]struct{}{}
			for _, optionItem := range asSlice(field["options"]) {
				option, ok := optionItem.(map[string]any)
				if !ok || option["value"] == nil {
					continue
				}
				allowed[fmt.Sprint(option["value"])] = struct{}{}
			}
			if len(allowed) > 0 {
				if _, ok := allowed[fmt.Sprint(value)]; !ok {
					invalid = append(invalid, label)
				}
			}
		}
	}
	if len(missing) > 0 {
		return BadRequest("插件购买字段缺失：" + strings.Join(missing, ", "))
	}
	if len(invalid) > 0 {
		return BadRequest("插件购买字段无效：" + strings.Join(invalid, ", "))
	}
	return nil
}

func present(value any) bool {
	if value == nil {
		return false
	}
	if text, ok := value.(string); ok {
		return strings.TrimSpace(text) != ""
	}
	return true
}

func truthy(value any) bool {
	switch v := value.(type) {
	case bool:
		return v
	case string:
		switch strings.ToLower(strings.TrimSpace(v)) {
		case "1", "true", "yes", "on", "required":
			return true
		default:
			return false
		}
	case int:
		return v != 0
	case int64:
		return v != 0
	case float64:
		return v != 0
	default:
		return false
	}
}
