package config

import (
	"net/http"
	"strings"
	"time"

	"hyapp/pkg/configx"
	"hyapp/pkg/logx"
	"hyapp/pkg/tencentim"
)

// Config 描述 activity-service 启动配置。
type Config struct {
	ServiceName string `yaml:"service_name"`
	NodeID      string `yaml:"node_id"`
	Environment string `yaml:"environment"`
	GRPCAddr    string `yaml:"grpc_addr"`
	// HealthHTTPAddr 是给 CLB/发布脚本探活使用的 HTTP 监听地址，不承载业务流量。
	HealthHTTPAddr string `yaml:"health_http_addr"`
	// MySQLDSN 是活动状态、事件消费幂等和 outbox 的必需存储连接串。
	MySQLDSN string `yaml:"mysql_dsn"`
	// UserServiceAddr 是 fanout worker 读取目标用户游标的内部 gRPC 地址。
	UserServiceAddr string `yaml:"user_service_addr"`
	// WalletServiceAddr 是任务奖励入账依赖；activity 只发命令，不直接写余额。
	WalletServiceAddr string `yaml:"wallet_service_addr"`
	// TencentIM 是 activity-service 发送全局/区域播报群消息的 REST 配置。
	TencentIM TencentIMConfig `yaml:"tencent_im"`
	// Broadcast 控制 IM 播报群 reconciler、outbox worker 和贵重礼物阈值。
	Broadcast BroadcastConfig `yaml:"broadcast"`
	// MySQLAutoMigrate 保留给显式本地迁移；线上 schema 由发布流程或 initdb 管理。
	MySQLAutoMigrate bool               `yaml:"mysql_auto_migrate"`
	Consumer         ConsumerConfig     `yaml:"consumer"`
	MessageInbox     MessageInboxConfig `yaml:"message_inbox"`
	Log              logx.Config        `yaml:"log"`
}

// ConsumerConfig 保存 room outbox 消费底座配置。
type ConsumerConfig struct {
	RoomOutboxPollIntervalMs int64 `yaml:"room_outbox_poll_interval_ms"`
	BatchSize                int   `yaml:"batch_size"`
}

// MessageInboxConfig 保存 App system/activity inbox 的读取缓存参数；fanout 扫描由 cron-service 调度。
type MessageInboxConfig struct {
	UnreadCacheTTL string `yaml:"unread_cache_ttl"`
}

// TencentIMConfig 描述 activity-service 调用腾讯云 IM REST API 的配置。
type TencentIMConfig struct {
	Enabled         bool          `yaml:"enabled"`
	SDKAppID        int64         `yaml:"sdk_app_id"`
	SecretKey       string        `yaml:"secret_key"`
	AdminIdentifier string        `yaml:"admin_identifier"`
	AdminUserSigTTL time.Duration `yaml:"admin_user_sig_ttl"`
	Endpoint        string        `yaml:"endpoint"`
	GroupType       string        `yaml:"group_type"`
	RequestTimeout  time.Duration `yaml:"request_timeout"`
}

// RESTConfig converts YAML into the shared Tencent IM REST client config.
func (c TencentIMConfig) RESTConfig() tencentim.RESTConfig {
	timeout := c.RequestTimeout
	if timeout <= 0 {
		timeout = 5 * time.Second
	}
	return tencentim.RESTConfig{
		SDKAppID:        c.SDKAppID,
		SecretKey:       c.SecretKey,
		AdminIdentifier: c.AdminIdentifier,
		AdminUserSigTTL: c.AdminUserSigTTL,
		Endpoint:        c.Endpoint,
		GroupType:       c.GroupType,
		HTTPClient:      &http.Client{Timeout: timeout},
	}
}

// BroadcastConfig stores activity-service broadcast worker policy.
type BroadcastConfig struct {
	Enabled               bool          `yaml:"enabled"`
	SuperGiftMinValue     int64         `yaml:"super_gift_min_value"`
	WorkerPollInterval    time.Duration `yaml:"worker_poll_interval"`
	WorkerBatchSize       int           `yaml:"worker_batch_size"`
	WorkerLockTTL         time.Duration `yaml:"worker_lock_ttl"`
	WorkerMaxRetry        int           `yaml:"worker_max_retry"`
	EnsureGroupsOnStartup bool          `yaml:"ensure_groups_on_startup"`
}

// Default 返回本地默认配置。
func Default() Config {
	return Config{
		ServiceName:       "activity-service",
		NodeID:            "activity-local",
		Environment:       "local",
		GRPCAddr:          ":13006",
		HealthHTTPAddr:    ":13106",
		MySQLDSN:          "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC",
		UserServiceAddr:   "127.0.0.1:13005",
		WalletServiceAddr: "127.0.0.1:13004",
		TencentIM: TencentIMConfig{
			Enabled:         false,
			AdminIdentifier: "administrator",
			AdminUserSigTTL: 24 * time.Hour,
			Endpoint:        tencentim.DefaultEndpoint,
			GroupType:       tencentim.DefaultGroupType,
			RequestTimeout:  5 * time.Second,
		},
		Broadcast: BroadcastConfig{
			Enabled:               false,
			SuperGiftMinValue:     100000,
			WorkerPollInterval:    time.Second,
			WorkerBatchSize:       100,
			WorkerLockTTL:         30 * time.Second,
			WorkerMaxRetry:        8,
			EnsureGroupsOnStartup: true,
		},
		MySQLAutoMigrate: false,
		Consumer: ConsumerConfig{
			RoomOutboxPollIntervalMs: 1000,
			BatchSize:                100,
		},
		MessageInbox: MessageInboxConfig{
			UnreadCacheTTL: "60s",
		},
		Log: logx.Config{
			Level:           "info",
			Format:          "json",
			MaxPayloadBytes: 2048,
		},
	}
}

// Load 从独立 config.yaml 读取 activity-service 配置。
func Load(path string) (Config, error) {
	cfg := Default()
	if path == "" {
		return cfg, nil
	}

	if err := configx.LoadYAML(path, &cfg); err != nil {
		return Config{}, err
	}
	if strings.TrimSpace(cfg.UserServiceAddr) == "" {
		cfg.UserServiceAddr = Default().UserServiceAddr
	}
	if strings.TrimSpace(cfg.WalletServiceAddr) == "" {
		cfg.WalletServiceAddr = Default().WalletServiceAddr
	}
	cfg.ServiceName = strings.TrimSpace(cfg.ServiceName)
	if cfg.ServiceName == "" {
		cfg.ServiceName = "activity-service"
	}
	cfg.NodeID = strings.TrimSpace(cfg.NodeID)
	if cfg.NodeID == "" {
		cfg.NodeID = cfg.ServiceName
	}
	cfg.Environment = strings.ToLower(strings.TrimSpace(cfg.Environment))
	if cfg.Environment == "" {
		cfg.Environment = "local"
	}
	cfg.HealthHTTPAddr = strings.TrimSpace(cfg.HealthHTTPAddr)
	if cfg.HealthHTTPAddr == "" {
		cfg.HealthHTTPAddr = ":13106"
	}
	cfg.TencentIM.AdminIdentifier = strings.TrimSpace(cfg.TencentIM.AdminIdentifier)
	if cfg.TencentIM.AdminIdentifier == "" {
		cfg.TencentIM.AdminIdentifier = "administrator"
	}
	cfg.TencentIM.Endpoint = strings.TrimSpace(cfg.TencentIM.Endpoint)
	if cfg.TencentIM.Endpoint == "" {
		cfg.TencentIM.Endpoint = tencentim.DefaultEndpoint
	}
	cfg.TencentIM.GroupType = strings.TrimSpace(cfg.TencentIM.GroupType)
	if cfg.TencentIM.GroupType == "" {
		cfg.TencentIM.GroupType = tencentim.DefaultGroupType
	}
	if cfg.TencentIM.AdminUserSigTTL <= 0 {
		cfg.TencentIM.AdminUserSigTTL = 24 * time.Hour
	}
	if cfg.TencentIM.RequestTimeout <= 0 {
		cfg.TencentIM.RequestTimeout = 5 * time.Second
	}
	if cfg.Broadcast.SuperGiftMinValue <= 0 {
		cfg.Broadcast.SuperGiftMinValue = 100000
	}
	if cfg.Broadcast.WorkerPollInterval <= 0 {
		cfg.Broadcast.WorkerPollInterval = time.Second
	}
	if cfg.Broadcast.WorkerBatchSize <= 0 {
		cfg.Broadcast.WorkerBatchSize = 100
	}
	if cfg.Broadcast.WorkerLockTTL <= 0 {
		cfg.Broadcast.WorkerLockTTL = 30 * time.Second
	}
	if cfg.Broadcast.WorkerMaxRetry <= 0 {
		cfg.Broadcast.WorkerMaxRetry = 8
	}

	return cfg, nil
}
