package admin_user

import (
	"context"

	"hm-server/app/main/api/internal/svc"
	"hm-server/app/main/api/internal/types"
	"hm-server/app/main/model"
	"hm-server/common/xerr"

	"github.com/pkg/errors"
	"github.com/samber/lo"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

type AdminUpdateUserLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewAdminUpdateUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateUserLogic {
	return &AdminUpdateUserLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *AdminUpdateUserLogic) AdminUpdateUser(req *types.AdminUpdateUserReq) (resp *types.AdminUpdateUserResp, err error) {
	// 检查用户是否存在
	user, err := l.svcCtx.AdminUserModel.FindOne(l.ctx, req.Id)
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户不存在: %v", err)
	}

	// 检查用户名是否重复
	if req.Username != nil && *req.Username != user.Username {
		exists, err := l.svcCtx.AdminUserModel.FindOneByUsername(l.ctx, *req.Username)
		if err != nil && err != model.ErrNotFound {
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新用户失败: %v", err)
		}
		if exists != nil {
			return nil, errors.Wrapf(xerr.NewErrMsg("用户名已存在"), "更新用户失败")
		}
	}

	// 更新用户信息
	if req.Username != nil {
		user.Username = *req.Username
	}
	if req.RealName != nil {
		user.RealName = *req.RealName
	}
	if req.Status != nil {
		user.Status = *req.Status
	}

	// 使用事务更新用户和关联角色
	err = l.svcCtx.AdminUserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		// 更新用户
		_, err = l.svcCtx.AdminUserModel.Update(ctx, session, user)
		if err != nil {
			return err
		}

		// 只有当RoleIds不为nil时才更新角色关联
		if req.RoleIds != nil {
			// 1. 获取当前关联的角色ID
			builder := l.svcCtx.AdminUserRoleModel.SelectBuilder().
				Where("user_id = ?", req.Id)
			currentRoles, err := l.svcCtx.AdminUserRoleModel.FindAll(ctx, builder, "id ASC")
			if err != nil {
				return err
			}

			// 2. 转换为map便于查找
			currentRoleMap := make(map[int64]*model.AdminUserRole)
			for _, role := range currentRoles {
				currentRoleMap[role.RoleId] = role
			}

			// 3. 检查新的角色ID是否存在
			for _, roleId := range req.RoleIds {
				exists, err := l.svcCtx.AdminRoleModel.FindOne(ctx, roleId)
				if err != nil || exists == nil {
					return errors.Wrapf(xerr.NewErrMsg("角色不存在"), "角色ID: %d", roleId)
				}
			}

			// 4. 找出需要删除和新增的关联
			var toDelete []*model.AdminUserRole
			var toInsert []int64

			// 需要删除的：当前存在但新列表中没有的
			for roleId, userRole := range currentRoleMap {
				if !lo.Contains(req.RoleIds, roleId) {
					toDelete = append(toDelete, userRole)
				}
			}

			// 需要新增的：新列表中有但当前不存在的
			for _, roleId := range req.RoleIds {
				if _, exists := currentRoleMap[roleId]; !exists {
					toInsert = append(toInsert, roleId)
				}
			}

			// 5. 删除需要移除的关联
			for _, userRole := range toDelete {
				err = l.svcCtx.AdminUserRoleModel.Delete(ctx, session, userRole.Id)
				if err != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除用户角色关联失败: %v", err)
				}
			}

			// 6. 添加新的关联
			for _, roleId := range toInsert {
				userRole := &model.AdminUserRole{
					UserId: req.Id,
					RoleId: roleId,
				}
				_, err = l.svcCtx.AdminUserRoleModel.Insert(ctx, session, userRole)
				if err != nil {
					return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "添加用户角色关联失败: %v", err)
				}
			}
		}

		return nil
	})

	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新用户失败: %v", err)
	}

	return &types.AdminUpdateUserResp{
		Success: true,
	}, nil
}
