package com.bonus.system.basic.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.bonus.common.core.constant.UserConstants;
import com.bonus.common.core.utils.FastJsonHelper;
import com.bonus.common.core.utils.ImportExcelUtils;
import com.bonus.common.core.utils.StringHelper;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.common.security.utils.ValidatorsUtils;
import com.bonus.system.api.domain.MapVo;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.att.utils.AddressCoordinateFormatUtil;
import com.bonus.system.att.utils.TreeUtils;
import com.bonus.system.basic.dao.SysOrgDao;
import com.bonus.system.basic.domain.SysNotice;
import com.bonus.system.basic.domain.SysOrg;
import com.bonus.system.basic.domain.SysOrgImport;
import com.bonus.system.basic.domain.SysTree;
import com.bonus.system.basic.domain.vo.TreeSelect;
import com.bonus.system.basic.service.SysNoticeService;
import com.bonus.system.basic.service.SysOrgService;
import com.bonus.system.dept.dao.ProDeptRoleDao;
import com.bonus.system.dept.service.SubOrgService;
import com.bonus.system.dept.service.SubOrgServiceImpl;
import com.bonus.system.holiday.entity.HolidayBean;
import com.bonus.system.holiday.entity.HolidayImportBean;
import com.bonus.system.holiday.entity.HolidayKeyBean;
import io.swagger.models.auth.In;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 组织 业务层处理
 *
 * @author zys
 */
@Service("sysOrgService")
public class SysOrgServiceImpl implements SysOrgService {

    @Resource
    private SysOrgDao orgDao;

    @Resource(name = "SubOrgService")
    private SubOrgServiceImpl service;

    /**
     * 消息推送库表
     */
    @Resource
    private SysNoticeService noticeService;

    @Resource(name = "ProDeptRoleDao")
    private ProDeptRoleDao proDeptRoleDao;

    @Resource
    private SysOrgDao sysOrgDao;

    @Override
    public List<SysOrg> selectOrgList(SysOrg sysOrg) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<String> roleId = sysUser.getRoleList();
        List<SysOrg> list = new ArrayList<>();
        //管理员与人资角色可以看到所有
        if (roleId != null && !roleId.isEmpty()) {
            if (Collections.frequency(roleId, "1") == 0 && Collections.frequency(roleId, "16") == 0) {
                // 根据用户id查询是否是部门负责人、部门考勤员
                Long userId = SecurityUtils.getUserId();
                List<MapVo> orgList = sysOrgDao.getOrgIdList(userId);
                if (!orgList.isEmpty() ) {
                    // 使用 LinkedHashSet 来保证顺序并自动去重
                    Set<String> idsSet = new LinkedHashSet<>();
                    for (MapVo mapVo : orgList) {
                        String id = proDeptRoleDao.getOrgChildById(mapVo.getId());
                        if (id != null && !id.trim().isEmpty()) { // 防止空或仅含空白字符的字符串
                            // 将分割后的数组添加到 Set 中，自动去重
                            Collections.addAll(idsSet, id.split(","));
                        }
                    }
                    // 如果需要转换回 List 类型
                    List<String> uniqueIds = new ArrayList<>(idsSet);
                    sysOrg.setOrgList(uniqueIds);
                    list = orgDao.selectOrgList(sysOrg);
                }else{
                    //剩下的人员全部只能看到自己的信息
                    sysOrg.setUserId(userId);
                    list = orgDao.selectOrgListPerson(sysOrg);
                }
            }else{
                list = orgDao.selectOrgList(sysOrg);
            }
        }
        return list;
    }

    @Override
    public List<SysOrg> selectOrgListAll(SysOrg sysOrg) {
        return orgDao.selectOrgList(sysOrg);
    }

    @Override
    public SysOrg selectOrgById(Long orgId) {
        return orgDao.selectOrgById(orgId);
    }

    @Override
    public List<TreeSelect> buildOrgTreeSelect(List<SysOrg> menus) {
        List<SysOrg> orgTrees = buildOrgTree(menus);
        return orgTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    @Override
    public int insertOrg(SysOrg org) {
//        if (org.getLat() == null || org.getLon()== null){
            Map<String, BigDecimal> map = AddressCoordinateFormatUtil.addressToCoordinate(org.getAddress());
            if (map == null) {
                return 3;
            }
            org.setLon(map.get("longitude"));
            org.setLat(map.get("latitude"));
//        }
        int i = orgDao.insertOrg(org);
        if (i > 0) {
            msgPush(org);
            if (StringUtils.isNotBlank(org.getOrgHeadUserId())) {
                return threadOrgHeadData(org);
            }

        }
        return i;
    }

    @Override
    public Boolean checkOrgNameUnique(SysOrg org) {
        long orgId = org.getId();
        SysOrg info = orgDao.checkOrgNameUnique(org.getOrgName(), org.getParentId());
        if (StringUtils.isNotNull(info) && info.getId() != orgId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public int updateOrg(SysOrg org) {
//        if (org.getLat() == null || org.getLon()== null){
            Map<String, BigDecimal> map = AddressCoordinateFormatUtil.addressToCoordinate(org.getAddress());
            if (map == null) {
                return 3;
            }
            org.setLon(map.get("longitude"));
            org.setLat(map.get("latitude"));
//        }
        int i = orgDao.updateOrg(org);
        if (i > 0) {
            if (StringUtils.isNotBlank(org.getOrgHeadUserId())) {
                orgDao.deleteOrgHead(org.getId());
                return threadOrgHeadData(org);
            }
        }
        return i;
    }

    public void msgPush(SysOrg org) {
        //获取部门负责人
        List<Long> userList = noticeService.getUserIdByOrgId(org.getParentId());
        Long loginId = SecurityUtils.getLoginUser().getSysUser().getUserId();
        // 将 List 转换为数组
        if (!userList.isEmpty()) {
            Long[] userIds = userList.toArray(new Long[0]);
            //发送审批消息
            SysNotice notice = new SysNotice();
            notice.setUserIds(userIds);
            notice.setUserId(loginId);
            notice.setTitle("项目部角色未配置");
            notice.setContent("项目部角色未配置");
            notice.setType("64");
            notice.setValue("");
            //推送消息
            noticeService.insertNotice(notice);
        }
    }


    public int threadOrgHeadData(SysOrg org) {
        List<String> listHead = new ArrayList<>();
        if (org.getOrgHeadUserId().contains(",")) {
            listHead = Arrays.asList(org.getOrgHeadUserId().split(","));
        } else {
            listHead.add(org.getOrgHeadUserId());
        }
        int j = orgDao.insertOrgHead(listHead, org.getId());
        if (j >= listHead.size()) {
            return 1;
        }
        return j;
    }

    @Override
    public boolean hasChildByOrgId(Long orgId) {
        int result = orgDao.hasChildByOrgId(orgId);
        return result > 0;
    }

    @Override
    public boolean checkOrgExistUser(Long orgId) {
        int result = orgDao.checkOrgExistUser(orgId);
        return result > 0;
    }

    @Override
    public int deleteOrgById(Long orgId) {
        Long updateUserId = SecurityUtils.getLoginUser().getSysUser().getUserId();
        service.syncDelRoleUser(orgId);
        return orgDao.deleteOrgById(orgId, updateUserId);

    }

    @Override
    public List<SysTree> orgPersonSelect() {
        List<SysTree> listTree = orgDao.orgPersonSelect();
        return listTree.stream().filter(m -> m.getParentId() == null).peek((m) ->
                m.setChildren(TreeUtils.getOrgTreeChild(m, listTree, 0))).collect(Collectors.toList());
    }

    @Override
    public String importData(MultipartFile file) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        ExcelUtil<SysOrgImport> util = new ExcelUtil<>(SysOrgImport.class);
        List<SysOrgImport> list = util.importExcel(file.getInputStream());
        if (!list.isEmpty()) {
            list.forEach(c -> {
                SysOrg sysOrg = getOrgData(c);
                if (!checkOrgNameUnique(sysOrg)) {
                    stringBuilder.append("导入异常：新增组织'").append(sysOrg.getOrgName())
                            .append("'失败，组织名称已存在;").append("\n");
                } else {
                    orgDao.insertOrg(sysOrg);
                    threadOrgHeadData(sysOrg);
                }
            });
        }
        return stringBuilder.toString();
    }

    @Resource(name = "ValidatorsUtils")
    private ValidatorsUtils validatorsUtils;

    @Override
    public AjaxResult orgUpload(MultipartFile file, HttpServletRequest request, HttpServletResponse response) {
        try {
            List<JSONObject> listObj = ImportExcelUtils.readExcel(file, SysOrgImport.class, "");
            List<SysOrgImport> list = new ArrayList<>();
            if (CollectionUtils.isEmpty(listObj)) {
                return AjaxResult.error("请勿导入空数据");
            }
            // 获取人员岗位
            for (JSONObject obj : listObj) {
                SysOrgImport vo = FastJsonHelper.jsonObjToBean(obj, SysOrgImport.class);
                String validResult = validatorsUtils.valid(vo, SysOrgImport.Query.class);
                if (org.apache.commons.lang3.StringUtils.isNotBlank(validResult)) {
                    return AjaxResult.error("第" + obj.getString("rowNo") + "行" + validResult);
                }
                list.add(vo);
            }
            // 校验库中数据的是否存在
            List<SysOrgImport> orgList = orgDao.getOrgList();
            List<SysOrgImport> personList = orgDao.getPersonList();
            int i = 0;
            for (SysOrgImport vo : list) {
                i++;
                if (codeIsExist(orgList, vo, 1)) {
                    return AjaxResult.error("第" + i + "行部门已存在");
                }
                if (!codeIsExist(orgList, vo, 2)) {
                    return AjaxResult.error("第" + i + "行上级部门不存在");
                }
//                if (!codeIsExist(personList, vo, 3)) {
//                    return AjaxResult.error("第" + i + "行部门负责人不存在");
//                }
//                if (!codeIsExist(personList, vo, 4)) {
//                    return AjaxResult.error("第" + i + "行考勤员不存在");
//                }
            }
            StringBuilder stringBuilder = new StringBuilder();
            if (!list.isEmpty()) {
                list.forEach(c -> {
                    SysOrg sysOrg = getOrgData(c);
                    if (!checkOrgNameUnique(sysOrg)) {
                        stringBuilder.append("导入异常：新增组织'").append(sysOrg.getOrgName())
                                .append("'失败，组织名称已存在;").append("\n");
                    } else {
                        orgDao.insertOrg(sysOrg);
                        if(!StringUtils.isEmpty(sysOrg.getOrgHeadUserId())){
                            threadOrgHeadData(sysOrg);
                        }
                    }
                });
            }
            if (stringBuilder.length() > 0) {
                return AjaxResult.error(stringBuilder.toString());
            } else {
                return AjaxResult.success();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判断导入部门、请假类型 是否存在
     *
     * @param list
     * @param value
     * @return boolean
     * @author fly
     * @date 2024/10/15 18:09
     */
    public boolean codeIsExist(List<SysOrgImport> list, SysOrgImport value, int type) {
        if (value == null) {
            throw new IllegalArgumentException("HolidayImportBean cannot be null.");
        }
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        if (type == 3) {
            String[] split = value.getOrgHeadUserName().split("[,，]");
            // 检查数组中的元素是否都存在于列表的name中
            return Arrays.stream(split)
                    .allMatch(name -> list.stream()
                            .anyMatch(item -> item.getOrgName().equals(name)));
        } else {
            for (SysOrgImport map : list) {
                String name = map.getOrgName();
                if (isMatch(type, name, value)) {
                    return true;
                }
            }
        }
        return false;
    }

    // 判断是否匹配
    private boolean isMatch(int type, String name, SysOrgImport value) {
        switch (type) {
            case 1:
                return Objects.equals(name, value.getOrgName());
            case 2:
                return Objects.equals(name, value.getParentName());
            case 3:
                return Objects.equals(name, value.getParentName());
            case 4:
                return Objects.equals(name, value.getAttendanceUserName());
            default:
                return false;
        }
    }


    private SysOrg getOrgData(SysOrgImport c) {
        SysOrg org = new SysOrg();
        Integer attendanceUserId = null;
        if(!StringUtils.isEmpty(c.getAttendanceUserName())){
            Map<String, Object> attendanceUserMap = orgDao.selectUserByName(c.getAttendanceUserName());
            attendanceUserId = (Integer) attendanceUserMap.get("userId");
        }
        String orgHeadUserId = "";
        if (StringUtils.isNotEmpty(c.getOrgHeadUserName())) {
            String replace = c.getOrgHeadUserName().replace("，", ",");
            c.setOrgHeadUserName(replace);
            if (c.getOrgHeadUserName().contains(",")) {
                List<String> list = Arrays.asList(c.getOrgHeadUserName().split(","));
                StringJoiner joiner = new StringJoiner(",");
                list.forEach(v -> {
                    Map<String, Object> orgHeadUserUserMap = orgDao.selectUserByName(v);
                    joiner.add(orgHeadUserUserMap.get("userId").toString());
                });
                orgHeadUserId = joiner.toString();
            } else {
                orgHeadUserId = orgDao.selectUserByName(c.getOrgHeadUserName()).get("userId").toString();
            }
        }
        org.setOrgHeadUserId(orgHeadUserId);
        String isDepartment = "是".equals(c.getIsDepartment()) ? "1" : "0";
        String isProvince = "省内".equals(c.getIsProvince()) ? "1" : "2";
        BigDecimal lat = new BigDecimal("0.0");
        BigDecimal lon = new BigDecimal("0.0");
        Map<String, BigDecimal> addressMap = AddressCoordinateFormatUtil.addressToCoordinate(c.getAddress());
        if (addressMap != null) {
            lon = addressMap.get("longitude");
            lat = addressMap.get("latitude");
        }
        Long parentId = orgDao.getParentIdByName(c.getParentName());
        org.setOrgName(c.getOrgName());
        org.setParentId(parentId);
        org.setAttendanceUserId(attendanceUserId + "");
        org.setIsDepartment(isDepartment);
        org.setIsProvince(isProvince);
        org.setProvince(c.getProvince());
        org.setLon(lon);
        org.setLat(lat);
        org.setAddress(c.getAddress());
        org.setCreateUserId(SecurityUtils.getLoginUser().getSysUser().getUserId());
        return org;
    }

    public List<SysOrg> buildOrgTree(List<SysOrg> menus) {
        List<SysOrg> returnList = new ArrayList<>();
        List<Long> tempList = menus.stream().map(SysOrg::getId).collect(Collectors.toList());
        for (SysOrg org : menus) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(org.getParentId())) {
                recursionFn(menus, org);
                returnList.add(org);
            }
        }
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list 分类表
     * @param t    子节点
     */
    private void recursionFn(List<SysOrg> list, SysOrg t) {
        // 得到子节点列表
        List<SysOrg> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysOrg tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysOrg> getChildList(List<SysOrg> list, SysOrg t) {
        List<SysOrg> lists = new ArrayList<>();
        for (SysOrg n : list) {
            if (n.getParentId() != null) {
                if (n.getParentId() == t.getId()) {
                    lists.add(n);
                }
            }
        }
        return lists;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysOrg> list, SysOrg t) {
        return !getChildList(list, t).isEmpty();
    }

}
