package mysql

import (
	"context"
	"database/sql"
	"errors"

	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	broadcastdomain "hyapp/services/activity-service/internal/domain/broadcast"
)

// ensureGameWinBroadcastConfigTable 只创建按 app_code 主键读取的小配置表。
// 本地自动迁移需要它保持开箱可用；线上仍由版本化 migration 先执行，避免服务启动临时持有 DDL 锁。
func (r *Repository) ensureGameWinBroadcastConfigTable(ctx context.Context) error {
	_, err := r.db.ExecContext(ctx, `
		CREATE TABLE IF NOT EXISTS game_win_broadcast_configs (
		  app_code VARCHAR(32) NOT NULL COMMENT '应用编码，用于多租户隔离',
		  enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否发送游戏中奖飘屏',
		  min_win_coins BIGINT NOT NULL COMMENT '单次返奖达到该金币数才发送飘屏',
		  updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID',
		  created_at_ms BIGINT NOT NULL COMMENT '创建时间，UTC epoch ms',
		  updated_at_ms BIGINT NOT NULL COMMENT '更新时间，UTC epoch ms',
		  PRIMARY KEY (app_code)
		) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游戏中奖飘屏配置'`)
	return err
}

// GetGameWinBroadcastConfig 通过 app_code 主键点查当前策略；未配置由 service 返回安全默认值。
func (r *Repository) GetGameWinBroadcastConfig(ctx context.Context) (broadcastdomain.GameWinConfig, bool, error) {
	if r == nil || r.db == nil {
		return broadcastdomain.GameWinConfig{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured")
	}
	var config broadcastdomain.GameWinConfig
	err := r.db.QueryRowContext(ctx, `
		SELECT enabled, min_win_coins, updated_by_admin_id, created_at_ms, updated_at_ms
		  FROM game_win_broadcast_configs
		 WHERE app_code = ?`, appcode.FromContext(ctx)).Scan(
		&config.Enabled,
		&config.MinWinCoins,
		&config.UpdatedByAdminID,
		&config.CreatedAtMS,
		&config.UpdatedAtMS,
	)
	if errors.Is(err, sql.ErrNoRows) {
		return broadcastdomain.GameWinConfig{}, false, nil
	}
	if err != nil {
		return broadcastdomain.GameWinConfig{}, false, err
	}
	return config, true, nil
}

// UpsertGameWinBroadcastConfig 原子替换当前 App 策略；创建时间保持不变，更新审计字段随每次保存推进。
func (r *Repository) UpsertGameWinBroadcastConfig(ctx context.Context, config broadcastdomain.GameWinConfig) (broadcastdomain.GameWinConfig, error) {
	if r == nil || r.db == nil {
		return broadcastdomain.GameWinConfig{}, xerr.New(xerr.Unavailable, "mysql repository is not configured")
	}
	_, err := r.db.ExecContext(ctx, `
		INSERT INTO game_win_broadcast_configs (
		  app_code, enabled, min_win_coins, updated_by_admin_id, created_at_ms, updated_at_ms
		) VALUES (?, ?, ?, ?, ?, ?)
		ON DUPLICATE KEY UPDATE
		  enabled = VALUES(enabled),
		  min_win_coins = VALUES(min_win_coins),
		  updated_by_admin_id = VALUES(updated_by_admin_id),
		  updated_at_ms = VALUES(updated_at_ms)`,
		appcode.FromContext(ctx), config.Enabled, config.MinWinCoins, config.UpdatedByAdminID, config.CreatedAtMS, config.UpdatedAtMS,
	)
	if err != nil {
		return broadcastdomain.GameWinConfig{}, err
	}
	stored, exists, err := r.GetGameWinBroadcastConfig(ctx)
	if err != nil {
		return broadcastdomain.GameWinConfig{}, err
	}
	if !exists {
		return broadcastdomain.GameWinConfig{}, xerr.New(xerr.Unavailable, "game win broadcast config was not persisted")
	}
	return stored, nil
}
