package commerce

import (
	"context"
	"encoding/json"
	"fmt"
	"math"
	"strconv"
	"strings"
)

type cartPricing struct {
	Cycle      string
	UnitPrice  float64
	AddonPrice float64
	SetupFee   float64
	TotalCents int
}

func (s *Service) calculateCartPricing(ctx context.Context, product Product, cycle string, quantity int, sliderValues map[string]any) (cartPricing, error) {
	cycle = strings.TrimSpace(cycle)
	if cycle == "" {
		return cartPricing{}, BadRequest("计费周期不正确")
	}
	if quantity <= 0 {
		quantity = 1
	}

	var pricing ProductPricing
	err := s.db.WithContext(ctx).
		Where("product_id = ? AND cycle = ? AND is_enabled = ?", product.ID, cycle, true).
		First(&pricing).Error
	if err != nil {
		if errorsIsRecordNotFound(err) {
			return cartPricing{}, BadRequest(fmt.Sprintf("产品「%s」的 %s 定价不存在或未启用", product.Name, cycle))
		}
		return cartPricing{}, err
	}
	if pricing.Price < 0 || pricing.SetupFee < 0 {
		return cartPricing{}, BadRequest("产品价格配置不正确")
	}

	addon, err := productSliderAddonPrice(product, sliderValues)
	if err != nil {
		return cartPricing{}, err
	}
	unitCents := yuanToCents(pricing.Price)
	addonCents := yuanToCents(addon)
	setupCents := yuanToCents(pricing.SetupFee)
	return cartPricing{
		Cycle:      cycle,
		UnitPrice:  pricing.Price,
		AddonPrice: addon,
		SetupFee:   pricing.SetupFee,
		TotalCents: (unitCents+addonCents)*quantity + setupCents,
	}, nil
}

func productSliderAddonPrice(product Product, sliderValues map[string]any) (float64, error) {
	if product.APIType == "plugin" {
		return 0, nil
	}
	total := 0.0
	for _, raw := range jsonList(product.ProvisionConfig) {
		field, ok := raw.(map[string]any)
		if !ok {
			continue
		}
		if strings.TrimSpace(fmt.Sprint(firstNonNilCommerce(field["type"], "fixed"))) != "slider" {
			continue
		}
		key := configFieldKeyCommerce(field["def"])
		if key == "" {
			continue
		}
		min := floatFromAny(field["slider_min"], 0)
		max := floatFromAny(field["slider_max"], min)
		step := floatFromAny(field["slider_step"], 1)
		unitPrice := floatFromAny(field["slider_unit_price"], 0)
		selected := min
		if sliderValues != nil {
			if rawValue, ok := sliderValues[key]; ok {
				selected = floatFromAny(rawValue, min)
			}
		}
		if selected < min || selected > max {
			return 0, BadRequest(fmt.Sprintf("%s 超出允许范围", configFieldLabelCommerce(field, key)))
		}
		if step > 0 {
			steps := (selected - min) / step
			if math.Abs(steps-math.Round(steps)) > 0.000001 {
				return 0, BadRequest(fmt.Sprintf("%s 不符合步长要求", configFieldLabelCommerce(field, key)))
			}
		}
		if unitPrice > 0 && selected > min {
			total += (selected - min) * unitPrice
		}
	}
	if total < 0 {
		return 0, BadRequest("附加配置价格不正确")
	}
	return total, nil
}

func firstNonNilCommerce(values ...any) any {
	for _, value := range values {
		if value != nil {
			return value
		}
	}
	return nil
}

func configFieldKeyCommerce(value any) string {
	text := strings.TrimSpace(fmt.Sprint(value))
	if text == "" || text == "<nil>" {
		return ""
	}
	if idx := strings.Index(text, "|"); idx >= 0 {
		return strings.TrimSpace(text[:idx])
	}
	return text
}

func configFieldLabelCommerce(field map[string]any, fallback string) string {
	text := strings.TrimSpace(fmt.Sprint(field["def"]))
	if idx := strings.Index(text, "|"); idx >= 0 && idx+1 < len(text) {
		label := strings.TrimSpace(text[idx+1:])
		if label != "" {
			return label
		}
	}
	return fallback
}

func floatFromAny(value any, fallback float64) float64 {
	switch v := value.(type) {
	case float64:
		return v
	case float32:
		return float64(v)
	case int:
		return float64(v)
	case int64:
		return float64(v)
	case int32:
		return float64(v)
	case json.Number:
		if f, err := v.Float64(); err == nil {
			return f
		}
	case string:
		if f, err := strconv.ParseFloat(strings.TrimSpace(v), 64); err == nil {
			return f
		}
	}
	return fallback
}
