package payment

import (
	"bytes"
	"encoding/json"
	"fmt"
	"math"
	"regexp"
	"strconv"
	"strings"
)

// 依次尝试：微信等常带 ¥；支付宝等到账文案多为「收款x.xx元」无货币符号。
var mengyaNoticeAmountPatterns = []*regexp.Regexp{
	regexp.MustCompile(`到账[¥￥]\s*([\d]+(?:\.[\d]+)?)`),
	regexp.MustCompile(`到账\s*([\d]+(?:\.[\d]+)?)\s*元`),
	regexp.MustCompile(`收款[¥￥]\s*([\d]+(?:\.[\d]+)?)(?:\s*元)?`),
	regexp.MustCompile(`收款\s*([\d]+(?:\.[\d]+)?)\s*元`),
}

// AmountEpsilon：Webhook 到账金额与订单快照金额对比时的容差。
const AmountEpsilon = 0.005

func AmountAlmostEqual(expected, actual float64) bool {
	return math.Abs(expected-actual) < AmountEpsilon
}

// ParseWebhookJSON 从转发通知体中解析支付金额：
// 优先 body.notice，其次顶层 notice，否则在序列化后的 JSON 字符串中扫描。
func ParseWebhookJSON(raw []byte) (float64, bool) {
	if len(bytes.TrimSpace(raw)) == 0 {
		return 0, false
	}
	var top map[string]json.RawMessage
	if err := json.Unmarshal(raw, &top); err != nil {
		return scanAmount(string(raw))
	}
	if v, ok := top["notice"]; ok {
		if s := jsonString(v); s != "" {
			return scanAmount(s)
		}
	}
	if inner, ok := top["body"]; ok {
		var nested map[string]json.RawMessage
		if json.Unmarshal(inner, &nested) == nil {
			if v, ok := nested["notice"]; ok {
				if s := jsonString(v); s != "" {
					return scanAmount(s)
				}
			}
			if amt, ok := scanAmount(jsonString(inner)); ok {
				return amt, ok
			}
			return scanAmount(string(inner))
		}
		if amt, ok := scanAmount(strings.Trim(strings.Trim(string(inner), "\""), `"`)); ok {
			return amt, ok
		}
		return scanAmount(string(inner))
	}
	buf, _ := json.Marshal(top)
	return scanAmount(string(buf))
}

func jsonString(raw json.RawMessage) string {
	var s string
	if json.Unmarshal(raw, &s) == nil {
		return s
	}
	return ""
}

func scanAmount(text string) (float64, bool) {
	if amt, ok := parseAmountRegex(text); ok {
		return amt, true
	}
	return parseAmountRegex(strings.ReplaceAll(text, `\n`, "\n"))
}

func parseAmountRegex(text string) (float64, bool) {
	for _, re := range mengyaNoticeAmountPatterns {
		match := re.FindStringSubmatch(text)
		if len(match) < 2 {
			continue
		}
		s := strings.ReplaceAll(match[1], ",", "")
		yuan, err := strconv.ParseFloat(s, 64)
		if err != nil {
			continue
		}
		return yuan, true
	}
	return 0, false
}

// NoticeFieldsForLog 从常见萌芽/转发 JSON 里抽出 notice 等字段，仅供后台日志排查（如微信/支付宝文案差异）。
func NoticeFieldsForLog(raw []byte) string {
	if len(bytes.TrimSpace(raw)) == 0 {
		return ""
	}
	var top map[string]json.RawMessage
	if err := json.Unmarshal(raw, &top); err != nil {
		return ""
	}
	var parts []string
	add := func(k, v string) {
		if v == "" {
			return
		}
		if len(v) > 600 {
			v = v[:600] + "…"
		}
		parts = append(parts, fmt.Sprintf("%s=%s", k, strconv.Quote(v)))
	}
	if v, ok := top["notice"]; ok {
		add("notice", jsonString(v))
	}
	if inner, ok := top["body"]; ok {
		var nested map[string]json.RawMessage
		if json.Unmarshal(inner, &nested) == nil {
			if v, ok := nested["notice"]; ok {
				add("body.notice", jsonString(v))
			}
			if v, ok := nested["content"]; ok {
				add("body.content", jsonString(v))
			}
			if v, ok := nested["text"]; ok {
				add("body.text", jsonString(v))
			}
		} else if s := jsonString(inner); s != "" {
			add("body(string)", s)
		}
	}
	for _, k := range []string{"title", "msg", "message", "desc", "description"} {
		if v, ok := top[k]; ok {
			add(k, jsonString(v))
		}
	}
	if len(parts) == 0 {
		return ""
	}
	return strings.Join(parts, "; ")
}
