package mysql

import (
	"context"

	"gorm.io/gorm"

	"github.com/pingcap-inc/it-automation/internal/sync-google-email/model"
)

type user struct {
	db *gorm.DB
}

func newUser(ds *datastore) *user {
	return &user{db: ds.db}
}

func (u *user) GetUser(s string) (*model.LarkUser, error) {
	var res model.LarkUser
	err := u.db.Where("email = ? or authingId = ?", s, s).First(&res).Error
	return &res, dbNotFoundErrorWrap(err)
}

func (u *user) SaveUsers(users []*model.LarkUser) error {
	tx := u.db.Begin()
	for _, us := range users {
		err := tx.Save(&us).Error
		if err != nil {
			tx.Rollback()

			return err
		}
	}
	tx.Commit()

	return nil
}

func (u *user) SaveUser(user *model.LarkUser) error {
	return u.db.Save(user).Error
}

func (u *user) ListUsers(_ context.Context) (users []*model.LarkUser, err error) {
	users = make([]*model.LarkUser, 1000)
	err = u.db.Find(&users).Error

	return users, dbNotFoundErrorWrap(err)
}

func (u *user) Create(_ context.Context, user *model.LarkUser) error {
	return u.db.Create(user).Error
}

func (u *user) GetAllUsers(_ context.Context) ([]model.LarkUser, error) {
	var users []model.LarkUser
	err := u.db.Find(&users).Error

	return users, err
}

func (u *user) GetUsersByLarkIds(ctx context.Context, luids []string) ([]model.LarkUser, error) {
	var users []model.LarkUser
	err := u.db.Where("larkUserId in (?)", luids).Find(&users).Error
	return users, err
}

func (u *user) SyncUser(_ context.Context, userCreate []model.LarkUser, userUpdate []model.LarkUser) error {
	tx := u.db.Begin()

	if len(userCreate) > 0 {
		err := tx.Create(&userCreate).Error
		if err != nil {
			tx.Rollback()
			return err
		}
	}

	for _, user := range userUpdate {
		err := tx.Save(&user).Error
		if err != nil {
			tx.Rollback()
			return err
		}
	}

	tx.Commit()

	return nil
}

func (u *user) BatchDeleteNotIn(_ context.Context, larkIds []string) error {
	tx := u.db.Begin()

	err := tx.Where("larkUserId not in ?", larkIds).Delete(&model.LarkUser{}).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()

	return nil
}

func (u *user) Save(ctx context.Context, user model.LarkUser) error {
	return u.db.Save(&user).Error
}

func (u *user) BatchSave(ctx context.Context, users []*model.LarkUser) error {
	tx := u.db.Begin()
	for _, user := range users {
		err := tx.Save(user).Error
		if err != nil {
			tx.Rollback()

			return err
		}
	}
	tx.Commit()

	return nil
}
