package com.wms_main.service.controller.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wms_main.constant.AppConstant;
import com.wms_main.dao.ITAppStandService;
import com.wms_main.dao.ITSysMenuService;
import com.wms_main.dao.ITSysUserService;
import com.wms_main.model.dto.response.wms.WmsApiResponse;
import com.wms_main.model.po.TAppStand;
import com.wms_main.model.po.TSysMenu;
import com.wms_main.model.po.TSysUser;
import com.wms_main.model.vo.wms.*;
import com.wms_main.repository.utils.StringUtils;
import com.wms_main.service.controller.ILoginControllerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import static com.wms_main.model.dto.response.wms.WmsApiResponse.error;
import static com.wms_main.model.dto.response.wms.WmsApiResponse.success;

/**
 * 登录控制类服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class LoginControllerServiceImpl implements ILoginControllerService {
    private final ITSysUserService userService;// User服务
    private final ITSysMenuService menuService;// Menu服务
    private final ITAppStandService appStandService;// 站台服务

    /**
     * 实现
     * @param loginAccount 登录账户
     * @param loginPassword 登录密码
     * @param ip IP地址
     * @return 结果
     */
    @Override
    public WmsApiResponse<UserLoginVo> loginWithAuth(String loginAccount, String loginPassword, String ip) {
        return genLoginResponse(loginAccount, loginPassword, ip, 1);
    }

    /**
     * 实现
     * @param loginAccount 登录账户
     * @param ip IP地址
     * @return 结果
     */
    @Override
    public WmsApiResponse<UserLoginVo> loginWithOutAuth(String loginAccount, String ip) {
        return genLoginResponse(loginAccount, "", ip, 2);
    }

    /**
     * 处理登录
     * @param loginAccount 登录账户
     * @param loginPassword 登录密码
     * @param ip ip地址
     * @param loginType 登录类型；1：账号密码登录；2：免密登录
     * @return 结果
     */
    private WmsApiResponse<UserLoginVo> genLoginResponse(String loginAccount, String loginPassword, String ip, int loginType) {
        // 检验登录账号是否输入
        if(StringUtils.isEmpty(loginAccount)) {
            return error("请输入账号。", null);
        }
        // 判断账号是否正确
        TSysUser user;
        if (loginType == 1) {
            user = userService.getUserWithAuth(loginAccount, loginPassword);
        } else {
            user = userService.getUserWithOutAuth(loginAccount);
        }
        if (user == null) {
            return error("账号或密码不正确。", null);
        }
        // 开始设置登录返回信息
        UserLoginVo userLoginVo = new UserLoginVo();
        // 设置用户信息
        userLoginVo.setUser(UserVo.ofPo(user));
        // 通过角色获取到所有菜单选项
        userLoginVo.setMenuList(getMenuVoListByRoleId(user.getRoleId()));
        // 根据请求的ip获取站台相关信息
        userLoginVo.setStand(getStandVoByLoginIp(ip));

        return success("登录成功。", userLoginVo);
    }

    /**
     * 根据roleId获取到菜单列表
     * @param roleId 角色id
     * @return 菜单列表
     */
    private List<MenuVo> getMenuVoListByRoleId(String roleId) {
        if (StringUtils.isEmpty(roleId)) {
            return Collections.emptyList();
        }
        List<TSysMenu> menuPoList;
        if (roleId.equals(AppConstant.ADMIN_ID)) {
            // 管理员获得所得菜单权限
            menuPoList = menuService.list();
        } else {
            menuPoList = menuService.selMenuByRoleId(roleId);
        }
        List<MenuVo> menuVoList = new LinkedList<>();
        // 查找一级菜单
        // TODO 这里可以用递归优化，减少代码量
        for (TSysMenu firstMenu : menuPoList) {
            if (AppConstant.ROOT_MENU_ID.equals(firstMenu.getParentId())) {// 查找到所有的一级子菜单
                MenuVo tempFirstMenu = new MenuVo();
                tempFirstMenu.setId(firstMenu.getMenuId());// ID
                tempFirstMenu.setLabelName(firstMenu.getLabelName());// 菜单显示名称
                tempFirstMenu.setIconValue(firstMenu.getIconValue());// 图标
                tempFirstMenu.setPath(firstMenu.getPath());// 路径
                // 设置二级菜单
                List<MenuVo> tempFirstMenuChildren = new LinkedList<>();
                for (TSysMenu secondMenu : menuPoList) {
                    if (firstMenu.getMenuId().equals(secondMenu.getParentId())) {
                        MenuVo tempSecondMenu = new MenuVo();
                        tempSecondMenu.setId(secondMenu.getMenuId());// ID
                        tempSecondMenu.setLabelName(secondMenu.getLabelName());// 菜单显示名称
                        tempSecondMenu.setIconValue(secondMenu.getIconValue());// 图标
                        tempSecondMenu.setPath(secondMenu.getPath());// 路径
                        // 设置按钮
                        List<MenuVo> tempSecondMenuChildren = new LinkedList<>();
                        for (TSysMenu thirdMenu : menuPoList) {
                            if (secondMenu.getMenuId().equals(thirdMenu.getParentId())) {
                                MenuVo tempThirdMenu = new MenuVo();
                                tempSecondMenu.setId(thirdMenu.getMenuId());// ID
                                tempSecondMenu.setLabelName(thirdMenu.getLabelName());// 菜单显示名称
                                tempSecondMenu.setIconValue(thirdMenu.getIconValue());// 图标
                                tempSecondMenu.setPath(thirdMenu.getPath());// 路径
                                // 添加按钮
                                tempSecondMenuChildren.add(tempThirdMenu);
                            }
                        }
                        tempSecondMenu.setChildren(tempSecondMenuChildren);
                        // 添加二级菜单
                        tempFirstMenuChildren.add(tempSecondMenu);
                    }
                }
                tempFirstMenu.setChildren(tempFirstMenuChildren);
                // 添加一级菜单
                menuVoList.add(tempFirstMenu);
            }
        }

        return menuVoList;
    }

    /**
     * 根据登录IP获取站台信息
     * @param loginIp 登录ip
     * @return 返回结果
     */
    private StandVo getStandVoByLoginIp(String loginIp) {
        StandVo standVo = new StandVo();
        List<TAppStand> standPoList = appStandService.list(new LambdaQueryWrapper<TAppStand>().eq(TAppStand::getStandIp, loginIp));
        if (standPoList == null || standPoList.isEmpty()) {
            // 非工作站台
            standVo.setStandId("非工作站台");
            standVo.setStandType(99);
        } else {
            // 多个选项只设置第一个
            standVo.setStandId(standPoList.getFirst().getStandId());
            standVo.setStandType(standPoList.getFirst().getStandType());
        }
        return standVo;
    }
}
