package mysql

import (
	"context"
	"strings"
	"time"
)

const (
	// StatTZUTC 是历史默认口径，保留它可以让旧接口、旧报表和跨服务 UTC 统计规则继续稳定工作。
	StatTZUTC = "UTC"
	// StatTZAsiaShanghai 是 Databi 需要的中国自然日口径；中国当前无夏令时，固定 +08:00 能避免容器缺 tzdata 时切日失败。
	StatTZAsiaShanghai = "Asia/Shanghai"
)

var asiaShanghaiLocation = time.FixedZone(StatTZAsiaShanghai, 8*60*60)

type statDayScope struct {
	tz  string
	day string
}

type statTZScopeContextKey struct{}

// WithStatTZScope 限制当前聚合只写一个 stat_tz；实时消费不使用它，回灌任务用它避免重放历史事件时污染 UTC 口径。
func WithStatTZScope(ctx context.Context, statTZ string) context.Context {
	return context.WithValue(ctx, statTZScopeContextKey{}, normalizeStatTZ(statTZ))
}

func normalizeStatTZ(value string) string {
	switch strings.TrimSpace(value) {
	case StatTZAsiaShanghai:
		return StatTZAsiaShanghai
	case StatTZUTC, "":
		return StatTZUTC
	default:
		return StatTZUTC
	}
}

func statLocation(statTZ string) *time.Location {
	if normalizeStatTZ(statTZ) == StatTZAsiaShanghai {
		return asiaShanghaiLocation
	}
	return time.UTC
}

func statDayIn(ms int64, statTZ string) string {
	return time.UnixMilli(ms).In(statLocation(statTZ)).Format("2006-01-02")
}

func statDayScopes(ms int64) []statDayScope {
	// 同一条业务事实必须一次事务内写出两份读模型：UTC 行维持历史聚合，Asia/Shanghai 行给中国自然日大屏使用。
	return []statDayScope{
		{tz: StatTZUTC, day: statDayIn(ms, StatTZUTC)},
		{tz: StatTZAsiaShanghai, day: statDayIn(ms, StatTZAsiaShanghai)},
	}
}

func statDayScopesFromContext(ctx context.Context, ms int64) []statDayScope {
	if ctx != nil {
		if statTZ, ok := ctx.Value(statTZScopeContextKey{}).(string); ok {
			statTZ = normalizeStatTZ(statTZ)
			return []statDayScope{{tz: statTZ, day: statDayIn(ms, statTZ)}}
		}
	}
	return statDayScopes(ms)
}
