package com.template.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.template.annotation.DESRespondSecret;
import com.template.api.SmartDepartmentControllerAPI;
import com.template.common.utils.*;
import com.template.config.ControlConfig;
import com.template.model.pojo.SmartAuthority;
import com.template.model.pojo.SmartDepartment;
import com.template.model.pojo.SmartUser;
import com.template.model.request.insertDepartmentRequest;
import com.template.model.request.updateDepartmentRequest;
import com.template.model.result.CommonResult;
import com.template.model.result.PageUtils;
import com.template.model.vo.*;
import com.template.services.SmartAuthorityService;
import com.template.services.SmartDepartmentService;
import com.template.services.SmartUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.template.common.utils.AesTestOne.decrypt;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ceshi
 * @since 2023-12-04
 */
@RestController
//返回参数加密注解
@DESRespondSecret
public class SmartDepartmentController implements SmartDepartmentControllerAPI {

    @Resource
    private ControlConfig controlConfig;

    @Autowired
    private SmartUserService smartUserService;

    @Autowired
    private SmartAuthorityService smartAuthorityService;

    @Autowired
    private SmartDepartmentService smartDepartmentService;


    /**
     * 新增部门
     *
     * @param smartDepartment 部门数据
     * @param bindingResult
     * @return
     */
    @Override
    @DESRespondSecret(validated = true)
    public CommonResult insertSmartDepartment(insertDepartmentRequest smartDepartment, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        //百胜不允许部门名称重复
        int exist = smartDepartmentService.existDataByName(smartDepartment.getName());
        if (exist > 0) {
            return CommonResult.fail("同级部门中，" + smartDepartment.getName() + "部门名称数据已存在，请勿重复添加！");
        }

        SmartDepartment sd = new SmartDepartment();
        sd.setParentId(smartDepartment.getParentId());
        sd.setName(smartDepartment.getName());

        //region 百胜添加部门数据
        String appId = controlConfig.getAppId();
        String schoolno = controlConfig.getSchoolCode();
        String timestamp = TimeExchange.DateNowTimeStamo();
        String appSecret = controlConfig.getAppSecret();
        String url = controlConfig.getUrl() + "department/create";

        JSONObject jsonobject = new JSONObject();
        jsonobject.put("appid", appId);
        String str = "{\"department_name\":\"" + smartDepartment.getName() + "\"}";
        String aesStr = URLEncoder.encode(AesTestOne.encrypt(str, controlConfig.getAppSecret()), "UTF-8");
        jsonobject.put("data", aesStr);
        jsonobject.put("schoolno", schoolno);
        jsonobject.put("timestamp", timestamp);

        String md5Str = "appid=" + appId + "&data={\"department_name\":\"" + smartDepartment.getName() + "\"}" + "&schoolno=" + schoolno + "&timestamp=" + timestamp + "&key=" + appSecret;
        String sign = CommonUtil.MD5(md5Str);
        //sign签名
        jsonobject.put("sign", sign);

        //返回的结果中 code为1表示成功
        String bsResult = RequestUtils.httpPost(url, jsonobject.toJSONString());

        if (bsResult.contains("添加成功")) {
            ObjectMapper objectMapper = new ObjectMapper();
            BsDepartmentVo department = objectMapper.readValue(bsResult, BsDepartmentVo.class);

            // URL解码
            String decodedUrl = URLDecoder.decode(department.getData(), "UTF-8");

            BsDepartmentNoVo departmentData = objectMapper.readValue(decrypt(decodedUrl, controlConfig.getAppSecret()), BsDepartmentNoVo.class);
            sd.setBsDepartmentNo(departmentData.getDepartment_no());
        }
        //endregion

        int result = smartDepartmentService.insertSmartDepartment(sd);

        return result > 0 ? CommonResult.ok("添加成功") : CommonResult.fail("添加失败");
    }

    /**
     * 更新部门
     *
     * @param udr           部门数据
     * @param bindingResult
     * @return
     */
    @Override
    @DESRespondSecret(validated = true)
    public CommonResult updateSmartDepartmentById(updateDepartmentRequest udr, BindingResult bindingResult) throws Exception {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        SmartDepartment oldData = smartDepartmentService.getSmartById(udr.getId());
        if (oldData == null) {
            return CommonResult.fail("部门数据无效，修改失败");
        }

        //百胜不允许部门名称重复
        SmartDepartment exist = smartDepartmentService.getSmartByName(udr.getName());
        if (exist != null && !exist.getId().equals(udr.getId())) {
            return CommonResult.fail(udr.getName() + "部门名称数据已存在，请勿重复添加！");
        }

        SmartDepartment sd = new SmartDepartment();
        sd.setId(udr.getId());
        sd.setParentId(udr.getParentId());
        sd.setName(udr.getName());

        //region 百胜添加部门数据
        String appId = controlConfig.getAppId();
        String schoolno = controlConfig.getSchoolCode();
        String timestamp = TimeExchange.DateNowTimeStamo();
        String appSecret = controlConfig.getAppSecret();
        String url = controlConfig.getUrl() + "department/update";

        JSONObject jsonobject = new JSONObject();
        jsonobject.put("appid", appId);
        String str = "{\"department_no\":\"" + oldData.getBsDepartmentNo() + "\",\"department_name\":\"" + udr.getName() + "\"}";
        String aesStr = URLEncoder.encode(AesTestOne.encrypt(str, controlConfig.getAppSecret()), "UTF-8");
        jsonobject.put("data", aesStr);
        jsonobject.put("schoolno", schoolno);
        jsonobject.put("timestamp", timestamp);

        String md5Str = "appid=" + appId + "&data={\"department_no\":\"" + oldData.getBsDepartmentNo() + "\",\"department_name\":\"" + udr.getName() + "\"}" + "&schoolno=" + schoolno + "&timestamp=" + timestamp + "&key=" + appSecret;
        String sign = CommonUtil.MD5(md5Str);
        //sign签名
        jsonobject.put("sign", sign);

        //返回的结果中 code为1表示成功
        String bsResult = RequestUtils.httpPost(url, jsonobject.toJSONString());

        if (bsResult.contains("添加成功")) {
            ObjectMapper objectMapper = new ObjectMapper();
            BsDepartmentVo department = objectMapper.readValue(bsResult, BsDepartmentVo.class);

            // URL解码
            String decodedUrl = URLDecoder.decode(department.getData(), "UTF-8");

            BsDepartmentNoVo departmentData = objectMapper.readValue(decrypt(decodedUrl, controlConfig.getAppSecret()), BsDepartmentNoVo.class);
            sd.setBsDepartmentNo(departmentData.getDepartment_no());
        }
        //endregion

        int result = smartDepartmentService.updateSmartDepartment(sd);
        return result > 0 ? CommonResult.ok("修改成功") : CommonResult.fail("修改失败");
    }

    /**
     * 部门分页数据查询
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param name        查询名称
     * @return
     */
    @Override
    @DESRespondSecret(validated = true)
    public CommonResult queryPageSmartDepartments(int currentPage, int pageCount, String name) {
        PageUtils<SmartDepartment> result = smartDepartmentService.queryPageSmartDepartments(currentPage, pageCount, name);

        return CommonResult.ok(result);
    }


    @Override
    @DESRespondSecret(validated = true)
    public CommonResult deleteSmartDepartmentById(int id) {

        SmartDepartment data = smartDepartmentService.getSmartById(id);

        if (data == null) {
            return CommonResult.fail("当前数据不存在，删除失败！");
        }

        int result = smartDepartmentService.deleteSmartDepartmentById(id);

        return result > 0 ? CommonResult.ok("删除成功") : CommonResult.fail("删除失败");
    }

    /**
     * 根据部门名称查询部门树形图结构数据
     *
     * @param name 部门名称
     * @return
     */
    @Override
    @DESRespondSecret(validated = true)
    public CommonResult queryDepartmentTree(String name, String userhead) {
        //region 角色判断
        String userID = AesUtils.decrypt(userhead);
        SmartUser operateData = smartUserService.getSmartById(Integer.valueOf(userID));
        if (operateData == null) {
            return CommonResult.fail("用户信息不合法，无法查看");
        }

        QueryWrapper<SmartAuthority> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", operateData.getId());
        List<SmartAuthority> authorities = smartAuthorityService.getAuthorByKey(queryWrapper);
        if (authorities == null) {
            return CommonResult.fail("当前用户权限不足，无法查看对应部门数据");
        }

        if (authorities.size() <= 0) {
            return CommonResult.fail("当前用户权限不足，无法查看对应部门数据");
        }

        List<String> viewAuthors = new ArrayList<>();//部门查看权限
        List<String> manageAuthors = new ArrayList<>();//部门管理权限
        for (SmartAuthority author : authorities) {
            List<String> views = StringUtils.hasText(author.getDepartmentView().trim()) ? Arrays.asList(author.getDepartmentView().trim().split(",")) : new ArrayList<>();
            if (views != null && views.size() > 0) {
                viewAuthors.addAll(views);
            }

            List<String> manages = StringUtils.hasText(author.getDepartmentManage().trim()) ? Arrays.asList(author.getDepartmentManage().trim().split(",")) : new ArrayList<>();
            if (manages != null && manages.size() > 0) {
                manageAuthors.addAll(manages);
            }
        }

        List<SmartDepartment> result = smartDepartmentService.getSmartsByName(name);
        //region 往上查找上一级
        List<String> newViewAthors = new ArrayList<>();
        List<String> newManageAthors = new ArrayList<>();
        if (!viewAuthors.contains("1")) {
            //region
            for (String view : viewAuthors) {
                Optional<SmartDepartment> department = result.stream().filter(e -> e.getId().equals(Integer.valueOf(view))).findFirst();
                if (department != null && department.isPresent()) {
                    newViewAthors.add(String.valueOf(department.get().getParentId()));
                    newViewAthors.addAll(queryAllParentId(department.get().getParentId(), result));
                }
            }
            //endregion
        }
        newViewAthors.addAll(viewAuthors);

        if (!manageAuthors.contains("1")) {
            //region
            for (String view : manageAuthors) {
                Optional<SmartDepartment> department = result.stream().filter(e -> e.getId().equals(Integer.valueOf(view))).findFirst();
                if (department != null && department.isPresent()) {
                    newManageAthors.add(String.valueOf(department.get().getParentId()));
                    newManageAthors.addAll(queryAllParentId(department.get().getParentId(), result));
                }
            }
            //endregion
        }
        newManageAthors.addAll(manageAuthors);
        //endregion

        newViewAthors = (newViewAthors != null && newViewAthors.size() > 0) ? newViewAthors.stream().distinct().collect(Collectors.toList()) : newViewAthors;
        newManageAthors = (newManageAthors != null && newManageAthors.size() > 0) ? newManageAthors.stream().distinct().collect(Collectors.toList()) : newManageAthors;
        //endregion


        List<SmartDepartment> zeroResult = result.stream().filter(e -> e.getParentId().intValue() == 0).collect(Collectors.toList());
        List<DepartmentTreeVo> departments = new ArrayList<>();
        if (ObjectUtils.isEmpty(name)) {
            for (SmartDepartment data : zeroResult) {


                long existViewData = newViewAthors == null ? 0 : newViewAthors.stream().filter(e -> e.equals(data.getId().toString())).count();
                long existManageData = newManageAthors == null ? 0 : newManageAthors.stream().filter(e -> e.equals(data.getId().toString())).count();
                if (existViewData <= 0 && existManageData <= 0 && data.getParentId().intValue() != 0) {
                    continue;
                }

                DepartmentTreeVo newData = new DepartmentTreeVo().builder()
                        .id(data.getId())
                        .name(data.getName())
                        .parentId(data.getParentId())
                        .isManage(existManageData > 0 ? 1 : 0)
                        .build();

                List<DepartmentTreeVo> departmentTrees = QueryDepartmentTreeRecords(newData.getId(), result, newViewAthors, newManageAthors);
                newData.setChildren(departmentTrees);
                departments.add(newData);
            }
        } else {
            for (SmartDepartment data : result) {
                long existViewData = newViewAthors == null ? 0 : newViewAthors.stream().filter(e -> e.equals(data.getId().toString())).count();
                long existManageData = newManageAthors == null ? 0 : newManageAthors.stream().filter(e -> e.equals(data.getId().toString())).count();
                if (existViewData <= 0 && existManageData <= 0) {
                    continue;
                }

                DepartmentTreeVo newData = new DepartmentTreeVo().builder()
                        .id(data.getId())
                        .name(data.getName())
                        .parentId(data.getParentId())
                        .isManage(existManageData > 0 ? 1 : 0)
                        .build();
                departments.add(newData);
            }
        }

        return CommonResult.ok(departments);
    }


    private List<String> queryAllParentId(Integer parentId, List<SmartDepartment> lists) {
        List<String> newIds = new ArrayList<>();

        Optional<SmartDepartment> department = lists.stream().filter(e -> e.getId().equals(parentId)).findFirst();
        if (department != null && department.isPresent()) {
            if(department.get().getParentId().intValue() != 0){
                newIds.add(String.valueOf(department.get().getParentId()));
            }

            List<String> queryList = queryAllParentId(department.get().getParentId(), lists);
            newIds.addAll(queryList);
        }
        return newIds;
    }

    /**
     * 根据父级ID获取树形数据
     *
     * @param parentID 父级ID
     * @param lists    数据集合
     * @return
     */
    private List<DepartmentTreeVo> QueryDepartmentTreeRecords(Integer parentID, List<SmartDepartment> lists, List<String> viewDatas, List<String> manageDatas) {
        List<DepartmentTreeVo> newTrees = new ArrayList<>();

        List<SmartDepartment> datas = lists.stream().filter(e -> e.getParentId().equals(parentID)).collect(Collectors.toList());

        for (SmartDepartment data : datas) {
            long existViewData = viewDatas == null ? 0 : viewDatas.stream().filter(e -> e.equals(data.getId().toString())).count();
            long existManageData = manageDatas == null ? 0 : manageDatas.stream().filter(e -> e.equals(data.getId().toString())).count();
            if (existViewData <= 0 && existManageData <= 0) {
                continue;
            }

            DepartmentTreeVo item = DepartmentTreeVo.builder()
                    .id(data.getId())
                    .parentId(parentID)
                    .name(data.getName())
                    .isManage(existManageData > 0 ? 1 : 0)
                    .build();
            List<DepartmentTreeVo> news = QueryDepartmentTreeRecords(item.getId(), lists, viewDatas, manageDatas);
            if (news == null || news.size() == 0) {
                newTrees.add(item);
                continue;
            } else {
                item.setChildren(news);
                newTrees.add(item);
            }
        }

        return newTrees;
    }


    /**
     * 根据部门名称查询部门树形图结构数据
     *
     * @param name 部门名称
     * @return
     */
    @Override
    @DESRespondSecret(validated = true)
    public CommonResult queryAllDepartmentTree(String name, String userhead) {
        //region 角色判断
        String userID = AesUtils.decrypt(userhead);
        SmartUser operateData = smartUserService.getSmartById(Integer.valueOf(userID));
        if (operateData == null) {
            return CommonResult.fail("用户信息不合法，无法查看");
        }
        //endregion


        List<SmartDepartment> result = smartDepartmentService.getSmartsByName(name);

        List<SmartDepartment> zeroResult = result.stream().filter(e -> e.getParentId().intValue() == 0).collect(Collectors.toList());
        List<DepartmentTreeVo> departments = new ArrayList<>();
        if (ObjectUtils.isEmpty(name)) {
            for (SmartDepartment data : zeroResult) {
                DepartmentTreeVo newData = new DepartmentTreeVo().builder()
                        .id(data.getId())
                        .name(data.getName())
                        .parentId(data.getParentId())
                        .isManage(1)
                        .build();

                List<DepartmentTreeVo> departmentTrees = QueryAllDepartmentTreeRecords(newData.getId(), result);
                newData.setChildren(departmentTrees);
                departments.add(newData);
            }
        } else {
            for (SmartDepartment data : result) {
                DepartmentTreeVo newData = new DepartmentTreeVo().builder()
                        .id(data.getId())
                        .name(data.getName())
                        .parentId(data.getParentId())
                        .isManage(1)
                        .build();
                departments.add(newData);
            }
        }

        return CommonResult.ok(departments);
    }


    /**
     * 根据父级ID获取树形数据
     *
     * @param parentID 父级ID
     * @param lists    数据集合
     * @return
     */
    private List<DepartmentTreeVo> QueryAllDepartmentTreeRecords(Integer parentID, List<SmartDepartment> lists) {
        List<DepartmentTreeVo> newTrees = new ArrayList<>();

        List<SmartDepartment> datas = lists.stream().filter(e -> e.getParentId().equals(parentID)).collect(Collectors.toList());

        for (SmartDepartment data : datas) {
            DepartmentTreeVo item = DepartmentTreeVo.builder()
                    .id(data.getId())
                    .parentId(parentID)
                    .name(data.getName())
                    .isManage(1)
                    .build();
            List<DepartmentTreeVo> news = QueryAllDepartmentTreeRecords(item.getId(), lists);
            if (news == null || news.size() == 0) {
                newTrees.add(item);
                continue;
            } else {
                item.setChildren(news);
                newTrees.add(item);
            }
        }

        return newTrees;
    }
}

