package payment

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"gorm.io/datatypes"
	"hfb_sys/backend/internal/model"
	"hfb_sys/backend/internal/timeutil"
	"math"
	"strings"
	"time"
)

func toDTO(payment model.PaymentOrder) PaymentDTO {
	return PaymentDTO{
		ID:              payment.ID,
		PaymentNo:       payment.PaymentNo,
		OrderID:         payment.OrderID,
		OrderNo:         payment.OrderNo,
		PaymentConfigID: payment.PaymentConfigID,
		Provider:        payment.Provider,
		ThirdOrderID:    payment.ThirdOrderID,
		ProviderOrderID: payment.ProviderOrderID,
		PayWay:          payment.PayWay,
		JSPayFlag:       payment.JSPayFlag,
		AmountCent:      payment.AmountCent,
		Status:          payment.Status,
		TDCode:          payment.TDCode,
		JSPayURL:        payment.JSPayURL,
		JSPayInfo:       payment.JSPayInfo,
		Paid:            payment.Status == "paid",
		PaidAt:          payment.PaidAt,
		CreatedAt:       payment.CreatedAt,
		UpdatedAt:       payment.UpdatedAt,
	}
}
func paymentErrorSummary(status string, raw datatypes.JSON) (string, string) {
	if status != "failed" {
		return "", ""
	}
	if len(raw) == 0 {
		return "", ""
	}
	var payload map[string]any
	if err := json.Unmarshal(raw, &payload); err != nil {
		return "", ""
	}
	code := firstStringValue(payload, "code", "resp_code", "result_code", "error_code", "status")
	message := firstStringValue(payload, "msg", "message", "error", "error_message", "result_msg", "result_desc")
	return code, message
}
func moneyCent(value float64) int64 {
	return int64(math.Round(value * 100))
}
func parseCent(value string) int64 {
	var amount int64
	_, _ = fmt.Sscanf(value, "%d", &amount)
	return amount
}
func parseChannelTime(value string) *time.Time {
	if value == "" {
		return nil
	}
	for _, layout := range []string{"2006-01-02 15:04:05", "20060102150405", time.RFC3339} {
		parsed, err := time.ParseInLocation(layout, value, timeutil.ShanghaiLocation())
		if err == nil {
			return &parsed
		}
	}
	return nil
}
func jsonMap(value map[string]string) datatypes.JSON {
	if value == nil {
		return nil
	}
	raw, err := json.Marshal(value)
	if err != nil {
		return nil
	}
	return datatypes.JSON(raw)
}
func withRawSource(raw map[string]string, source string) map[string]string {
	out := map[string]string{}
	for key, value := range raw {
		out[key] = value
	}
	if source != "" {
		out["_source"] = source
	}
	out["_recorded_at"] = time.Now().Format(time.RFC3339)
	return out
}
func jsonString(value map[string]string) string {
	if len(value) == 0 {
		return "{}"
	}
	raw, err := json.Marshal(value)
	if err != nil {
		return "{}"
	}
	return string(raw)
}
func newPaymentNo() (string, error) {
	buf := make([]byte, 4)
	if _, err := rand.Read(buf); err != nil {
		return "", err
	}
	return fmt.Sprintf("PAY%d%s", time.Now().UnixNano(), hex.EncodeToString(buf)), nil
}
func firstNonEmpty(values ...string) string {
	for _, value := range values {
		if value != "" {
			return value
		}
	}
	return ""
}

// firstNonZero 返回第一个非零 uint64，用于保留历史支付单已有配置 ID。
func firstNonZero(values ...uint64) uint64 {
	for _, value := range values {
		if value != 0 {
			return value
		}
	}
	return 0
}

// normalizePayWay 将前端或渠道别名统一为系统内部支付方式编码。
func normalizePayWay(value string) string {
	switch strings.ToUpper(strings.TrimSpace(value)) {
	case "", "ZFBZF", "ALIPAY", "ALIPAYPAY":
		return "ZFBZF"
	case "WXZF", "WECHAT", "WECHATPAY":
		return "WXZF"
	default:
		return strings.ToUpper(strings.TrimSpace(value))
	}
}
