package mysql

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

	"hyapp/pkg/xerr"
)

// Repository 是 wallet-service 的 MySQL v2 账本入口。
type Repository struct {
	// db 是账户、交易、分录和 outbox 的同一事务边界。
	db *sql.DB
}

// Open 创建 MySQL 连接池并做启动 ping。
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 max_connections，必须显式设上限。
	db.SetMaxOpenConns(20)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(30 * time.Minute)

	if err := db.PingContext(ctx); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureGiftDiamondRatioSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureCoinSellerSalaryExchangeRateSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureUserResourceEquipmentSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureVipBenefitResourceBindingHistorySchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureExternalRechargeSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureResourceShopPurchaseOrderIndexes(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureHostSalarySettlementSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureResourceGrantRevokeSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureResourceGroupSnapshotSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureResourceEntitlementSnapshotSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureGooglePaymentPaidDetailsSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensureWalletPolicyInstanceSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}
	if err := ensurePointWithdrawalCoinSellerSchema(ctx, db); err != nil {
		_ = db.Close()
		return nil, err
	}

	return &Repository{db: db}, nil
}

// Close 释放 MySQL 连接池。
func (r *Repository) Close() error {
	if r == nil || r.db == nil {
		return nil
	}

	return r.db.Close()
}

// Ping 验证 MySQL 当前可用。
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)
}
