package app

import (
	"context"
	"net"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"hyapp/services/activity-service/internal/config"
	mysqlstorage "hyapp/services/activity-service/internal/storage/mysql"
)

type externalClients struct {
	userConn   *grpc.ClientConn
	walletConn *grpc.ClientConn
	roomConn   *grpc.ClientConn
}

func openRepository(ctx context.Context, cfg config.Config) (*mysqlstorage.Repository, error) {
	// activity-service 的活动配置、消费幂等、排行榜和 outbox 都落在 MySQL。
	// migrate 放在启动阶段执行，保证本地新增活动模块时不需要手工补表后才能启动。
	repository, err := mysqlstorage.Open(ctx, cfg.MySQLDSN)
	if err != nil {
		return nil, err
	}
	repository.SetActivityTemplateSettlementLateness(cfg.ActivityTemplateRuntime.SettlementLateness)
	if cfg.MySQLAutoMigrate {
		if err := repository.Migrate(ctx); err != nil {
			_ = repository.Close()
			return nil, err
		}
	}
	return repository, nil
}

func listenGRPC(addr string) (net.Listener, error) {
	return net.Listen("tcp", addr)
}

func dialExternalClients(cfg config.Config) (externalClients, error) {
	// 三个下游连接在 App 级别统一持有；各业务 service 只拿生成后的 typed client。
	// 这样 Close 时可以按连接维度回收资源，新增模块也不会重复创建 gRPC 连接池。
	var clients externalClients
	var err error
	clients.userConn, err = grpc.Dial(cfg.UserServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		return externalClients{}, err
	}
	clients.walletConn, err = grpc.Dial(cfg.WalletServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		clients.Close()
		return externalClients{}, err
	}
	clients.roomConn, err = grpc.Dial(cfg.RoomServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		clients.Close()
		return externalClients{}, err
	}
	return clients, nil
}

func (c externalClients) Close() {
	if c.roomConn != nil {
		_ = c.roomConn.Close()
	}
	if c.walletConn != nil {
		_ = c.walletConn.Close()
	}
	if c.userConn != nil {
		_ = c.userConn.Close()
	}
}
