package mysql

import (
	"context"
	"database/sql"
	"strings"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"hyapp/pkg/xerr"
)

// Repository 是 lucky-gift-service 的 MySQL 持久化入口。
// 幸运礼物的规则版本、RTP 窗口、单池水位、抽奖记录和返奖 outbox 必须落在同一个 owner 库，
// 调用方只能通过 service/grpc 进入，不能绕过事务边界直接修改这些表。
type Repository struct {
	db *sql.DB
}

// Open 创建幸运礼物服务专用连接池并做启动探活。
// DSN 必须指向 hyapp_lucky_gift；复用 activity 或 wallet 库会破坏 owner 边界，也会让 outbox 补偿读错事实。
func Open(ctx context.Context, dsn string) (*Repository, error) {
	if strings.TrimSpace(dsn) == "" {
		return nil, xerr.New(xerr.InvalidArgument, "mysql_dsn is required")
	}
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, err
	}
	// 标准库默认连接数不设限；幸运礼物抽奖会持有多张表行锁，必须限制并发连接避免压垮 MySQL。
	db.SetMaxOpenConns(20)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(30 * time.Minute)
	if err := db.PingContext(ctx); err != nil {
		_ = db.Close()
		return nil, err
	}
	return &Repository{db: db}, nil
}

// Migrate 只做本地/测试环境的轻量幂等兜底。
// 生产表结构仍以 deploy/mysql/initdb 和显式 migration 为准，避免服务启动时悄悄改动线上结构。
func (r *Repository) Migrate(ctx context.Context) error {
	if r == nil || r.db == nil {
		return xerr.New(xerr.Unavailable, "mysql repository is not configured")
	}
	// 当前拆分版本优先依赖完整初始化 SQL；这里保留探活，让 Docker 本地启动能在 DSN 错误时快速失败。
	return r.db.PingContext(ctx)
}

// Close 释放连接池；服务关闭时先停止 worker 再关库，避免补偿协程拿到已关闭连接。
func (r *Repository) Close() error {
	if r == nil || r.db == nil {
		return nil
	}
	return r.db.Close()
}

// Ping 给健康检查使用，只确认 owner 库可访问，不代表钱包或 IM 下游可用。
func (r *Repository) Ping(ctx context.Context) error {
	if r == nil || r.db == nil {
		return xerr.New(xerr.Unavailable, "mysql repository is not configured")
	}
	return r.db.PingContext(ctx)
}
