package authcenter

import (
	"context"
	"errors"
	"fmt"

	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/tiinf/errs"
	"gorm.io/gorm"
)

const (
	tableName = "auth_center_cluster_users"
)

type ClusterUserDaoIface interface {
	CreateClusterUser(ctx context.Context, tx *gorm.DB, user *entity.ClusterUser) (*entity.ClusterUser, error)
	UpdateClusterUserByID(ctx context.Context, tx *gorm.DB, user *entity.ClusterUser) error
	GetClusterUserByClusterIDUsername(ctx context.Context, tx *gorm.DB, clusterID uint64, username string) (*entity.ClusterUser, error)
	ListClusterUsersByClusterID(ctx context.Context, tx *gorm.DB, clusterID uint64) ([]entity.ClusterUser, error)
}

type ClusterUserDao struct {
}

func NewClusterUserDao() ClusterUserDaoIface {
	return &ClusterUserDao{}
}

func (dao *ClusterUserDao) CreateClusterUser(ctx context.Context, tx *gorm.DB, user *entity.ClusterUser) (*entity.ClusterUser, error) {
	err := tx.Table(tableName).Save(user).Error
	if err != nil {
		return nil, errs.WrapGORMError(err, fmt.Sprintf("CreateClusterUser error: %+v", user))
	}
	return user, nil
}

func (dao *ClusterUserDao) UpdateClusterUserByID(ctx context.Context, tx *gorm.DB, user *entity.ClusterUser) error {
	updateMap := map[string]interface{}{}

	if user.Credential != "" {
		updateMap["credential"] = user.Credential
	}
	if user.CredentialType != "" {
		updateMap["credential_type"] = user.CredentialType
	}
	if user.Description != "" {
		updateMap["description"] = user.Description
	}
	if user.CredentialUpdatedAt != nil {
		updateMap["credential_updated_at"] = user.CredentialUpdatedAt
	}
	if user.Status != "" {
		updateMap["status"] = user.Status
	}
	if user.UpdatedAt != nil {
		updateMap["updated_at"] = user.UpdatedAt
	}
	if user.TargetType != "" {
		updateMap["target_type"] = user.TargetType
	}
	if user.UserEmail != "" {
		updateMap["user_email"] = user.UserEmail
	}

	err := tx.Table(tableName).Where("id=?", user.ID.Uint64()).Updates(updateMap).Error
	if err != nil {
		return errs.WrapGORMError(err, fmt.Sprintf("UpdateClusterUserByID error: %+v", user))
	}

	return nil

}

func (dao *ClusterUserDao) GetClusterUserByClusterIDUsername(ctx context.Context, tx *gorm.DB, clusterID uint64, username string) (*entity.ClusterUser, error) {
	res := &entity.ClusterUser{}
	err := tx.Table(tableName).Where("cluster_id=? and username=?", clusterID, username).First(res).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, errs.WrapGORMError(err, fmt.Sprintf("GetClusterUserByClusterIDUsername error: %+v", clusterID))
	}
	return res, nil
}

func (dao *ClusterUserDao) ListClusterUsersByClusterID(ctx context.Context, tx *gorm.DB, clusterID uint64) ([]entity.ClusterUser, error) {
	var res []entity.ClusterUser
	err := tx.Table(tableName).Where("cluster_id=?", clusterID).Order("created_at desc, id desc").Find(&res).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, errs.WrapGORMError(err, fmt.Sprintf("ListClusterUsersByClusterID error: %+v", err))
	}
	return res, nil
}
