package mysql

import (
	"context"

	"github.com/pingcap-inc/pingcat/internal/pkg/code"
	v1 "github.com/pingcap-inc/pingcat/model/v1"
	"gorm.io/gorm"

	"github.com/pingcap-inc/pchub/pkg/errors"
)

type userOpenAI struct {
	db *gorm.DB
}

func newUserOpenAI(ds *datastore) *userOpenAI {
	return &userOpenAI{db: ds.db}
}

func (u *userOpenAI) GetByUser(_ context.Context, larkUID string) (*v1.UserOpenAI, error) {
	userOpenAI := &v1.UserOpenAI{}
	err := u.db.Where("userLarkID = ?", larkUID).First(userOpenAI).Error

	return userOpenAI, dbNotFoundErrorWrap(err)
}

func (u *userOpenAI) GetByID(_ context.Context, id uint64) (*v1.UserOpenAI, error) {
	userOpenAI := &v1.UserOpenAI{}
	err := u.db.Where("id = ?", id).First(userOpenAI).Error

	return userOpenAI, dbNotFoundErrorWrap(err)
}

func (u *userOpenAI) UpInsert(ctx context.Context, it *v1.UserOpenAI) (*v1.UserOpenAI, error) {
	tx := u.db.Begin()

	if it.ID == 0 && it.UserLarkID == "" {
		return nil, errors.WithCode(code.ErrNoUserLarkID, "no userLarkID")
	}

	var exist *v1.UserOpenAI
	if it.ID > 0 {
		userOpenAI := &v1.UserOpenAI{}
		err := tx.Where("id = ?", it.ID).First(userOpenAI).Error
		if err != nil {
			return nil, dbNotFoundErrorWrap(err)
		}
		exist = userOpenAI
	} else if it.UserLarkID != "" {
		userOpenAI := &v1.UserOpenAI{}
		err := tx.Where("userLarkID = ?", it.UserLarkID).First(userOpenAI).Error
		if err != nil {
			if !errors.Is(err, gorm.ErrRecordNotFound) {
				return nil, dbNotFoundErrorWrap(err)
			}
		} else {
			exist = userOpenAI
		}
	}

	if exist != nil {
		// update
		err := tx.Model(exist).Updates(it).Error
		if err != nil {
			tx.Rollback()

			return nil, err
		}
		tx.Commit()

		return exist, nil
	}

	// insert
	err := tx.Create(it).Error
	if err != nil {
		tx.Rollback()

		return nil, err
	}
	tx.Commit()

	return it, nil
}

func (u *userOpenAI) Delete(_ context.Context, it *v1.UserOpenAI) error {
	model := u.db
	if it.ID != 0 {
		model = model.Where("id = ?", it.ID)
	} else if it.UserLarkID != "" {
		model = model.Where("userLarkID = ?", it.UserLarkID)
	}
	err := model.Unscoped().Delete(&v1.UserOpenAI{}).Error

	return err
}
