package transactional_operation

import (
	"database/sql"
	"validate/dbctrl"
	"validate/util"

	"github.com/pingcap/errors"
)

func ExportDatabase(db *dbctrl.DatabaseInfo, dbAddress dbctrl.DBAddress) (*dbctrl.DatabaseInfo, error) {
	if db.IsSystemDatabase() {
		return nil, errors.New("System database will not be exported")
	}

	dbConnPool, err := dbctrl.NewDBConnInfo(dbAddress.Host,
		dbAddress.Port,
		db.SCHEMA_NAME,
		dbAddress.Account,
		dbAddress.Password)
	if err != nil {
		return nil, errors.Wrap(err, "")
	}

	curDBConn, err := dbConnPool.Connect()
	if err != nil {
		return nil, errors.Wrap(err, "")
	}
	dbInfo, err := exportDatabaseDetail(db, curDBConn)
	if err != nil {
		return nil, errors.Wrap(err, "failed to ")
	}

	if err = curDBConn.Close(); err != nil {
		util.Logger.Fatalf("failed to close DB connection to %s", db.SCHEMA_NAME)
	}

	return dbInfo, err
}

func exportDatabaseDetail(dbi *dbctrl.DatabaseInfo, db *sql.DB) (*dbctrl.DatabaseInfo, error) {
	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}
	defer func() {
		commitErr := tx.Commit()
		if commitErr != nil {
			util.Logger.Fatalf("failed to COMMIT transaction, " + commitErr.Error())
		}
	}()

	return dbi, dbi.ExportDatabaseDetail(tx)
}

func ExportDatabaseList(db *sql.DB) (dbList []*dbctrl.DatabaseInfo, err error) {
	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}
	defer func() {
		commitErr := tx.Commit()
		if commitErr != nil {
			util.Logger.Fatalf("failed to COMMIT transaction, " + commitErr.Error())
		}
	}()

	dbList, err = dbctrl.GetAllDatabase(tx)
	if err != nil {
		rollbackErr := tx.Rollback()
		if rollbackErr != nil {
			util.Logger.Fatalf("failed to ROLLBACK transaction, " + rollbackErr.Error())
		}
		return nil, err
	}

	return dbList, nil
}

func IsTableGoodForCDC(tbl *dbctrl.TableInformationSchema) bool {
	return tbl.HasPKOrUK()
}
