package main

import (
	"database/sql"
	"fmt"
	"math/rand"
	"time"

	"github.com/go-sql-driver/mysql"
	"github.com/tidbcloud/tiinf/transport/tieventbus"
	gmysql "gorm.io/driver/mysql"
	"gorm.io/gorm"
)

const (
	TxPubTable = "msg_store"
	EventType  = "test-tx-pub"
)

type D struct {
	ID int
}

func getMySQL() gorm.Dialector {
	conf := mysql.NewConfig()
	conf.Net = "tcp"
	conf.User = "root"
	conf.Addr = "localhost"
	db, err := sql.Open("mysql", conf.FormatDSN())
	if err != nil {
		panic(err)
	}
	DBName := fmt.Sprintf("example_%v", rand.Int())
	_, _ = db.Exec("DROP DATABASE " + DBName)
	_, err = db.Exec("CREATE DATABASE " + DBName)
	if err != nil {
		panic(err)
	}
	err = db.Close()
	if err != nil {
		panic(err)
	}
	conf.DBName = DBName
	return gmysql.Open(conf.FormatDSN())
}

func main() {
	gDB, err := gorm.Open(getMySQL(), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	db, err := gDB.DB()
	if err != nil {
		panic(err)
	}
	eventbus, err := tieventbus.NewEventbusMock(tieventbus.EventbusConfig{
		AppName:    "app",
		DB:         db,
		TxPubTable: TxPubTable,
	})
	if err != nil {
		panic(err)
	}
	recieved := make(chan struct{})
	eventbus.RegisterHandler(tieventbus.HandlerConfig{
		EventType: EventType,
		Group:     "1",
		HandleFunc: func(event *tieventbus.Event) error {
			fmt.Println("Event has been recieved")
			close(recieved)
			return nil
		},
		DataStruct: D{},
	})
	err = eventbus.Run()
	if err != nil {
		panic(err)
	}
	err = gDB.Transaction(func(gTx *gorm.DB) error {
		tx := gTx.Statement.ConnPool.(*sql.Tx)
		err := eventbus.PublishWithDBTx(tx, &tieventbus.Event{
			ID:   "1",
			Type: EventType,
			Data: &D{ID: 1},
		})
		if err != nil {
			return err
		}
		fmt.Println("Event has been sent")
		time.Sleep(5 * time.Second)
		fmt.Println("Event has been commit")
		return nil
	})
	if err != nil {
		panic(err)
	}
	select {
	case <-recieved:
	case <-time.After(5 * time.Second):
		panic("timeout")
	}
}
