package com.xy.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xy.collections.list.JArrayList;
import com.xy.collections.list.JList;
import com.xy.collections.map.JMap;
import com.xy.consts.CommConsts;
import com.xy.dto.SysMenuDto;
import com.xy.entity.*;
import com.xy.mapper.SysMenuMapper;
import com.xy.mapper.SysRoleMapper;
import com.xy.mapper.SysRoleMenuMapper;
import com.xy.mapper.SysSystemMapper;
import com.xy.redis.RedisCache;
import com.xy.service.SysMenuService;
import com.xy.service.SysRoleMenuService;
import com.xy.translate.baidu.TransApi;
import com.xy.utils.AuthorizeUtils;
import com.xy.utils.Emptys;
import com.xy.utils.MybatisPlusQuery;
import com.xy.utils.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;

import java.util.ArrayList;
import java.util.List;

import static com.xy.utils.Beans.copy;
import static com.xy.utils.Beans.tree;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author lijin
 * @since 2022-12-09
 */
@Slf4j
@Api(tags = "菜单管理")
@Service
@AllArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private SysRoleMenuMapper sysRoleMenuMapper;

    private SysRoleMapper sysRoleMapper;

    private SysRoleMenuService sysRoleMenuService;

    private SysSystemMapper sysSystemMapper;

    /**
     * 菜单全量翻译
     */
    @Async
    public void translateAllMenu() {
        List<SysMenu> sysMenus = this.list();
        List<SysMenu> updateMenus = new ArrayList<>();
        for (SysMenu sysMenu : sysMenus) {
            String name = sysMenu.getName();
            String enName = sysMenu.getEnName();
            if (StrUtil.isEmpty(enName)) {
                //百度api翻译
                String translatedValue = TransApi.translate(name, "zh", "en");
                sysMenu.setEnName(translatedValue);
                updateMenus.add(sysMenu);
                // 增加1.2秒的延迟
                try {
                    Thread.sleep(1800);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("线程中断异常", e);
                    return;
                }
            }
        }
        if (CollUtil.isNotEmpty(updateMenus)) {
            updateBatchById(updateMenus);
        }
    }

    @PostMapping("workMenu")
    @ApiOperation("用户菜单树")
    public R<List<SysMenuDto.Vo>> workMenu(@RequestBody @Validated SysMenuDto.WorkMenu workMenu) {
        List<SysMenuDto.Vo> list = new ArrayList<>();
        List<SysMenuJoinSysRoleMenu> menus = Emptys.check(workMenu.getClientType())
                ? RedisCache.getMenuTree(workMenu.getSysId(), workMenu.getClientType())
                : RedisCache.getMenuTree(workMenu.getSysId());
        menus.forEach(sysMenuJoinSysRoleMenu -> {
            SysMenuDto.Vo vo = copy(SysMenuDto.Vo.class, sysMenuJoinSysRoleMenu);
            List<SysMenuDto.Vo> sonVos = copy(SysMenuDto.Vo.class, sysMenuJoinSysRoleMenu.getSonSysMenu());
            list.add(vo.setSonSysMenu(sonVos));
        });
        return R.ok(list);
    }

    @PostMapping("workMenuList")
    @ApiOperation("用户菜单集合")
    public R<List<SysMenuDto.MenuVo>> workMenuList(@RequestHeader(value = "lang", required = false) String lang, @RequestBody @Validated SysMenuDto.WorkMenuList workMenu) {
        List<SysMenuDto.MenuVo> menuVos = new ArrayList<>();
        List<Long> sysIds = workMenu.getSysId();
        Long loginId = AuthorizeUtils.getLoginId(Long.class);
        List<SysSystem> sysSystems = sysSystemMapper.selectList(new LambdaQueryWrapper<SysSystem>().in(SysSystem::getId, sysIds));
        JMap<Long, SysSystem> sysSystemJMap = new JArrayList<>(sysSystems).toMap(SysSystem::getId).cover();
        for (Long sysId : sysIds) {
            List<SysMenuDto.Vo> list = new ArrayList<>();
            List<SysMenuJoinSysRoleMenu> menus = Emptys.check(workMenu.getClientType())
                    ? RedisCache.getMenu(sysId, workMenu.getClientType())
                    : RedisCache.getMenu(sysId);
            menus.forEach(sysMenuJoinSysRoleMenu -> list.add(copy(SysMenuDto.Vo.class, sysMenuJoinSysRoleMenu)));
//            if ("en".equals(lang)) {
//                //英文菜单
//                list.forEach(sm -> {
//                    String enName = sm.getEnName();
//                    if (StrUtil.isNotEmpty(enName)) {
//                        sm.setName(enName);
//                    }
//                });
//
//            }
            SysSystem sysSystem = sysSystemJMap.get(sysId);
            if (sysSystem == null) {
                continue;
            }
            SysMenuDto.MenuVo menuVo = new SysMenuDto.MenuVo()
                    .setId(sysId)
                    .setCode(sysSystem.getCode())
                    .setName(sysSystem.getName())
                    .setIcon(sysSystem.getIcon())
                    .setMenu(list);
//            if ("en".equals(lang) && "xy_merc_mini".equals(sysSystem.getCode())) {
//                //商管端
//                menuVo.setName("Business Management Platform");
//            }
            menuVos.add(menuVo);
        }
        return R.ok(menuVos);
    }

    @PostMapping("menu")
    @ApiOperation("系统菜单树")
    public R<List<SysMenuDto.Vo>> menu(@RequestBody SysMenuDto.SysMenu sysMenu) {
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(sysMenu, SysMenu.class).build().orderByAsc(SysMenu::getOrders);
        List<SysMenuDto.Vo> vos = copy(SysMenuDto.Vo.class, list(lambdaQueryWrapper));
        JList<SysMenuDto.Vo> list = new JArrayList<>(vos).filter().isNull(SysMenuDto.Vo::getPaterId).list();
        for (SysMenuDto.Vo vo : list) {
            List<SysMenuDto.Vo> tree = tree(vo, vos, SysMenuDto.Vo::getId, SysMenuDto.Vo::getPaterId, SysMenuDto.Vo::getSonSysMenu);
            vo.setSonSysMenu(tree);
        }
        return R.ok(list);
    }

    @PostMapping("save")
    @ApiOperation("添加菜单")
    public R save(@RequestBody @Validated SysMenuDto.Save save) {
        //校验数据
        if (save.getType() != 1 && !Emptys.check(save.getInterfaceUri())) {
            return R.fail("非目录时interfaceUri不能为空");
        }
        long count = count(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getCode, save.getCode())
                .eq(SysMenu::getSysId, save.getSysId())
        );
        if (count > 0) {
            return R.fail("标识已存在");
        }
        //添加菜单
        SysMenu sysMenu = copy(SysMenu.class, save)
                .create(RedisCache.getLoginId(Long.class));
        save(sysMenu);
        //赋予管理员角色菜单
        SysRole sysRole = sysRoleMapper.selectOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getSysId, save.getSysId()).eq(SysRole::getCode, CommConsts.ADMIN_ROLE_CODE));
        SysRoleMenu sysRoleMenu = new SysRoleMenu()
                .createId()
                .setSelectAdmin(true)
                .setMenuId(sysMenu.getId())
                .setRoleId(sysRole.getId());
        sysRoleMenuMapper.insert(sysRoleMenu);
        return R.ok();
    }

    @PostMapping("update")
    @ApiOperation("修改菜单")
    public R update(@RequestBody @Validated SysMenuDto.Update update) {
        SysMenu sysMenu = copy(SysMenu.class, update)
                .update(RedisCache.getLoginId(Long.class));
        updateById(sysMenu);
        return R.ok();
    }

    @PostMapping("del")
    @ApiOperation("删除菜单")
    public R del(@RequestBody @Validated SysMenuDto.Del del) {
        delMethod(del);
        return R.ok();
    }

    @PostMapping("getMenuIdsForAdmin")
    @ApiOperation("获取角色的管理员权限菜单")
    public R<List<Long>> getMenuIdsForAdmin(@RequestBody @Validated SysMenuDto.RoleAdminMenuIdsDto roleAdminMenuIdsDto) {
        List<Long> menuIds = sysRoleMenuService.getMenuIdsByRoleId(roleAdminMenuIdsDto.getRoleId(), Boolean.TRUE);
        return R.ok(menuIds);
    }

    private void delMethod(SysMenuDto.Del del) {
        //删除角色菜单
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getMenuId, del.getId()));
        //删除菜单
        removeBatchByIds(del.getId());
        //删除子级
        List<SysMenu> list = list(new LambdaQueryWrapper<SysMenu>().in(SysMenu::getPaterId, del.getId()));
        if (Emptys.check(list)) {
            SysMenuDto.Del del2 = new SysMenuDto.Del().setId(new JArrayList<>(list).getProperty(SysMenu::getId));
            delMethod(del2);
        }
    }

}
