package internal

import (
	"context"
	"github.com/gogf/gf/util/guid"
	"strings"
	"yx-dataset-server/app/errors"
	"yx-dataset-server/app/model"
	"yx-dataset-server/app/schema"
	"yx-dataset-server/library/redis"
	"yx-dataset-server/library/utils"
)

// NewUser 创建User
func NewUser(
	mUser model.IUser,
	mUserDataset model.IUserDataset,
	mTrans model.ITrans,
	mMenu model.IMenu,
	mRoleMenu model.IRoleMenu,
	mDataset model.IDataset,
	mOrganization model.IOrganization,
	mRole model.IRole,
) *User {
	return &User{
		UserModel:        mUser,
		userDatasetModel: mUserDataset,
		transModel:       mTrans,
		menuModel:        mMenu,
		roleMenuModel:    mRoleMenu,
		datasetModel:     mDataset,
		orgModel:         mOrganization,
		roleModel:        mRole,
	}
}

// User 创建User对象
type User struct {
	UserModel        model.IUser
	userDatasetModel model.IUserDataset
	transModel       model.ITrans
	menuModel        model.IMenu
	roleMenuModel    model.IRoleMenu
	datasetModel     model.IDataset
	orgModel         model.IOrganization
	roleModel        model.IRole
}

// Query 查询数据
func (a *User) Query(ctx context.Context, params schema.UserQueryParam, opts ...schema.UserOptions) (*schema.UserQueryResult, error) {
	result, err := a.UserModel.Query(ctx, params, opts...)
	if err != nil {
		return nil, err
	}
	result.Data.FillCreator(result.Data)
	for _, v := range result.Data {
		v.Used, _ = redis.GetRedisClient().Get(ctx, "chart:user:"+v.RecordID).Int()
		v.Unused = v.ChartNum - v.Used

	}

	roles, err := a.roleModel.Query(ctx, schema.RoleQueryParam{})
	if err != nil {
		return nil, err
	}
	result.Data.FillRoleName(roles.Data)

	orgs, err := a.orgModel.Query(ctx, schema.OrganizationQueryParam{})
	if err != nil {
		return nil, err
	}
	result.Data.FillOrgName(orgs.Data)

	return result, nil
}

// Get 查询指定数据
func (a *User) Get(ctx context.Context, recordID string, opts ...schema.UserOptions) (*schema.User, error) {
	if CheckIsRootUser(ctx) {
		return a.getRootInfo(ctx)
	}
	item, err := a.UserModel.Get(ctx, recordID, opts...)
	if err != nil {
		return nil, err
	} else if item == nil {
		return nil, errors.ErrNotFound
	}

	// 查询用户菜单
	roleMenu, err := a.roleMenuModel.Query(ctx, schema.RoleMenuQueryParam{RoleId: item.RoleId})
	if err != nil {
		return nil, err
	}
	menus, err := a.menuModel.Query(ctx, schema.MenuQueryParam{RecordIDs: roleMenu.Data.ToMenuIds()})
	if err != nil {
		return nil, err
	}
	item.Menu = menus.Data.ToTrees()

	role, err := a.roleModel.Get(ctx, item.RoleId)
	if err != nil {
		return nil, err
	}
	item.RoleName = role.Name

	org, err := a.orgModel.Get(ctx, item.OrgId)
	if err != nil {
		return nil, err
	}
	item.OrgName = org.Name

	// 查询用户可访问的知识库
	userDataset, err := a.userDatasetModel.Query(ctx, schema.UserDatasetQueryParam{UserId: recordID})
	if err != nil {
		return nil, err
	}
	dataset, err := a.datasetModel.Query(ctx, schema.DatasetQueryParam{RecordIds: userDataset.Data.ToDatasetIds()})
	if err != nil {
		return nil, err
	}
	userDataset.Data.FillDatasetName(dataset.Data)

	item.Datasets = userDataset.Data

	item.Used, _ = redis.GetRedisClient().Get(ctx, "chart:user:"+item.RecordID).Int()
	item.Unused = item.ChartNum - item.Used
	return item, nil

}

func (a *User) getUpdate(ctx context.Context, recordID string) (*schema.User, error) {
	return a.Get(ctx, recordID)
}

// Create 创建数据
func (a *User) Create(ctx context.Context, item schema.User) error {
	item.RecordID = guid.S()
	item.Status = true
	item.Password = utils.SHA1HashString(strings.ToUpper(item.Password))
	err := ExecTrans(ctx, a.transModel, func(ctx context.Context) error {
		if len(item.Datasets) > 0 {
			for _, v := range item.Datasets {
				err := a.userDatasetModel.Create(ctx, schema.UserDataset{
					UserId:    item.RecordID,
					DatasetId: v.DatasetId,
					Type:      v.Type,
				})
				if err != nil {
					return err
				}
			}
		}

		return a.UserModel.Create(ctx, item)
	})
	return err
}

// Update 更新数据
func (a *User) Update(ctx context.Context, recordID string, item schema.User) error {
	oldItem, err := a.UserModel.Get(ctx, recordID)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.ErrNotFound
	}
	if item.Password != "" {
		item.Password = utils.SHA1HashString(strings.ToUpper(item.Password))
	}
	err = ExecTrans(ctx, a.transModel, func(ctx context.Context) error {
		err = a.userDatasetModel.DeleteByUserId(ctx, recordID)
		if err != nil {
			return err
		}
		if len(item.Datasets) > 0 {
			for _, v := range item.Datasets {
				err := a.userDatasetModel.Create(ctx, schema.UserDataset{
					UserId:    item.RecordID,
					DatasetId: v.DatasetId,
					Type:      v.Type,
				})
				if err != nil {
					return err
				}
			}
		}
		return nil
	})
	err = a.UserModel.Update(ctx, recordID, item)
	if err != nil {
		return err
	}
	return nil
}

// Delete 删除数据
func (a *User) Delete(ctx context.Context, recordID string) error {
	oldItem, err := a.UserModel.Get(ctx, recordID)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.ErrNotFound
	}
	err = ExecTrans(ctx, a.transModel, func(ctx context.Context) error {
		err = a.userDatasetModel.DeleteByUserId(ctx, recordID)
		if err != nil {
			return err
		}
		return a.UserModel.Delete(ctx, recordID)
	})
	return err
}

// UpdateStatus 更新状态
func (a *User) UpdateStatus(ctx context.Context, recordID string, status bool) error {
	oldItem, err := a.UserModel.Get(ctx, recordID)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.ErrNotFound
	}
	return a.UserModel.UpdateStatus(ctx, recordID, status)
}

func (a *User) getRootInfo(ctx context.Context) (*schema.User, error) {
	user := GetRootUser()
	user.Password = "******"
	menu, err := a.menuModel.Query(ctx, schema.MenuQueryParam{})
	if err != nil {
		return nil, err
	}
	user.Menu = menu.Data.ToTrees()
	return user, nil
}
