package com.gci.boot.modules.system.controller;


import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.gci.boot.common.log.annotation.AddSysLog;
import com.gci.boot.common.util.ParamsCheckUtil;
import com.gci.boot.common.util.QueryWrapperUtil;
import com.gci.boot.common.vo.Result;
import com.gci.boot.modules.system.entity.SysDepart;
import com.gci.boot.modules.system.service.ISysDepartService;
import com.gci.boot.modules.system.vo.LoginUser;
import com.gci.boot.modules.system.vo.SysDepartTreeModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * <p>
 * 组织机构表 前端控制器
 * </p>
 *
 * @author chenzhiwei
 * @since 2023-08-31
 */
@RestController
@RequestMapping("/sys/depart")
@Slf4j
public class SysDepartController {

    @Autowired
    private ISysDepartService sysDepartService;


    /**
     * 查询数据 查出所有部门,并以树结构数据格式响应给前端
     *
     * @return
     */
    @AddSysLog("查询部门")
    @GetMapping("/queryTreeList")
    public Result<List<SysDepartTreeModel>> queryTreeList(String name, SysDepart sysDepart) {
        try {
            if(StringUtils.isNotBlank(name)){
                sysDepart.setDepartName(name);
            }

            return Result.ok(queryDepartTree(sysDepart));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error("获取部门失败！");
    }


    private List<SysDepartTreeModel> queryDepartTree(SysDepart sysDepart){
        List<SysDepartTreeModel> res = new ArrayList<>();
        Map<String, SysDepartTreeModel> allMap = new HashMap<>();
        Map<String, List<SysDepartTreeModel>> childrenMap = new HashMap<>();
        QueryWrapper<SysDepart> queryWrapper = QueryWrapperUtil.builder().table(SysDepart.class)
                .like(SysDepart::getDepartName)
                .orderByAsc(SysDepart::getDepartOrder)
                .buildFromObject(sysDepart);

        sysDepartService.list(queryWrapper).forEach(i -> {
            SysDepartTreeModel t = new SysDepartTreeModel();
            BeanUtils.copyProperties(i, t);
            allMap.put(t.getId(), t);
            if (StringUtils.isBlank(i.getParentId())) {
                res.add(t);
            } else {
                List<SysDepartTreeModel> children = childrenMap.get(t.getParentId());
                if (children == null) {
                    children = new ArrayList<>();
                    childrenMap.put(t.getParentId(), children);
                }
                children.add(t);
            }
        });
        childrenMap.forEach((k, v) -> {
            SysDepartTreeModel t = allMap.get(k);
            if (t != null) {
                t.setChildren(v);
            }else{
                res.addAll(v);
            }
        });
        return res;
    }
    @AddSysLog("查询部门")
    @GetMapping("/querySubTree")
    public Result<List<SysDepartTreeModel>> querySubTree(SysDepart sysDepart) {
        try {
            if(StringUtils.isBlank(sysDepart.getOrgCode())){
                LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                if(sysUser != null){
                    sysDepart.setOrgCode(sysUser.getOrgCode());
                }
            }
            SysDepart one = sysDepartService.lambdaQuery().eq(SysDepart::getOrgCode, sysDepart.getOrgCode()).one();
            if(one.getOrgCategory() != null && (one.getOrgCategory() == 2 || one.getOrgCategory() == 3)){
                Map<String, SysDepartTreeModel> allMap = new HashMap<>();
                List<SysDepartTreeModel> res = new ArrayList<>();
                List<String> idList = new ArrayList<>();
                SysDepartTreeModel t = new SysDepartTreeModel();
                BeanUtils.copyProperties(one, t);
                allMap.put(t.getId(), t);
                res.add(t);
                idList.add(one.getId());

                while(idList.size()>0){
                    List<SysDepart> list = sysDepartService.lambdaQuery()
                            .in(SysDepart::getParentId, idList)
                            .orderByAsc(SysDepart::getDepartOrder)
                            .list();
                    idList.clear();
                    list.forEach(i->{
                        SysDepartTreeModel tr = new SysDepartTreeModel();
                        BeanUtils.copyProperties(i, tr);
                        allMap.put(tr.getId(), tr);
                        SysDepartTreeModel parent = allMap.get(tr.getParentId());
                        if(parent != null){
                            if(parent.getChildren() == null){
                                parent.setChildren(new ArrayList<>());
                            }
                            parent.getChildren().add(tr);
                        }
                        idList.add(i.getId());
                    });
                }
                return Result.ok(res);
            }


            return Result.ok(queryDepartTree(new SysDepart()));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error("获取部门失败！");
    }

    /**
     * 添加部门
     *
     * @param sysDepart
     * @return
     */
    @AddSysLog("添加部门")
    @PostMapping("/add")
    public Result<SysDepart> add(@RequestBody SysDepart sysDepart) {
        ParamsCheckUtil.paramsAssert()
                .notBlank(sysDepart.getOrgCode(), "【机构编码】不能为空！")
                .notBlank(sysDepart.getDepartName(), "【机构名称】不能为空！")
                .notNull(sysDepart.getOrgCategory(), "【机构类型】不能为空！")
                .isTrue(sysDepartService.lambdaQuery().eq(SysDepart::getOrgCode, sysDepart.getOrgCode()).count() == 0, "【机构编码】已存在！");
        if(StringUtils.isBlank(sysDepart.getParentId())){
            ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().and(w->w.isNull(SysDepart::getParentId).or().eq(SysDepart::getParentId, "")).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称！");
        }else{
            ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().eq(SysDepart::getParentId, sysDepart.getParentId()).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称！");
        }
        sysDepartService.save(sysDepart);
        return Result.ok("添加成功！");
    }

    /**
     * 编辑数据 编辑部门的部分数据,并保存到数据库
     *
     * @param sysDepart
     * @return
     */
    @AddSysLog("编辑部门")
    @PutMapping("/edit")
    public Result<SysDepart> edit(@RequestBody SysDepart sysDepart) {
        SysDepart sysDepartEntity = sysDepartService.getById(sysDepart.getId());
        if (sysDepartEntity == null) {
            return Result.error("未找到对应部门!");
        }
        ParamsCheckUtil.paramsAssert()
                .notBlank(sysDepart.getOrgCode(), "【机构编码】不能为空！")
                .notBlank(sysDepart.getDepartName(), "【机构名称】不能为空！")
                .notNull(sysDepart.getOrgCategory(), "【机构类型】不能为空！")
                .isTrue(sysDepartService.lambdaQuery()
                .ne(SysDepart::getId, sysDepart.getId())
                .eq(SysDepart::getOrgCode, sysDepart.getOrgCode()).count() == 0, "【机构编码】已存在！");
        if(StringUtils.isBlank(sysDepartEntity.getParentId())){
            ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().and(w->w.isNull(SysDepart::getParentId).or().eq(SysDepart::getParentId, "")).ne(SysDepart::getId, sysDepart.getId()).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称！");
        }else{
            ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().ne(SysDepart::getId, sysDepart.getId()).eq(SysDepart::getParentId, sysDepartEntity.getParentId()).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称！");
        }
        sysDepartService.updateById(sysDepart);
        return Result.ok("编辑成功！");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AddSysLog("删除部门")
    @DeleteMapping("/delete")
    public Result<SysDepart> delete(String id) {
        SysDepart sysDepart = sysDepartService.getById(id);
        if (sysDepart == null) {
            return Result.error("未找到对应实体");
        }
        Integer count = sysDepartService.lambdaQuery().eq(SysDepart::getParentId, id).count();
        if(count > 0){
            return Result.error("存在下级部门，无法删除！");
        }
        sysDepartService.removeById(id);
        return Result.ok("删除成功！");
    }


    /**
     * 批量删除 根据前端请求的多个ID,对数据库执行删除相关部门数据的操作
     *
     * @param ids
     * @return
     */
    @AddSysLog("批量删除部门")
    @DeleteMapping("/deleteBatch")
    public Result<SysDepart> deleteBatch(String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("参数不识别！");
        }
        this.sysDepartService.deleteBatchWithChildren(Arrays.asList(ids.split(",")));
        return Result.ok("删除成功!");
    }

    @PostMapping("/importExcel")
    public Result<?> simpleImport(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            try(InputStream input = file.getInputStream()) {
                List<SysDepart> list = EasyExcel.read(input).head(SysDepart.class).sheet().doReadSync();
                log.info("数据量：{}",list.size());
                for(SysDepart d : list){
                    List<SysDepart> one = sysDepartService.lambdaQuery().eq(SysDepart::getDepartName, d.getDepartName()).list();
                    if(one.size()>0){
                        d.setId(one.get(0).getId());
                    }
                }
                sysDepartService.saveOrUpdateBatch(list);
            }catch (IOException e){
                return Result.error("导入错误！");
            }
        }
        return Result.ok();
    }

    @GetMapping("/exportExcel")
    public Result<?> export(String name, HttpServletResponse response){
        try (OutputStream output = response.getOutputStream()){

            String fileName = "部门信息.xlsx";
            try {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName);

            List<SysDepart> list = sysDepartService.lambdaQuery()
                    .like(StringUtils.isNotBlank(name), SysDepart::getDepartName, name)
                    .orderByAsc(SysDepart::getDepartOrder)
                    .list();
            EasyExcel.write(output, SysDepart.class).sheet("sheet1").doWrite(list);

        } catch (IOException e) {
            return Result.error("导出错误！");
        }
        return Result.ok();
    }
}
