package com.ruoyi.busi.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.busi.constant.BusiCacheConstants;
import com.ruoyi.busi.domain.SysOrg;
import com.ruoyi.busi.domain.vo.SysOrgOperateVO;
import com.ruoyi.busi.domain.vo.SysOrgQuery;
import com.ruoyi.busi.domain.vo.SysOrgTreeSelect;
import com.ruoyi.busi.mapper.SysOrgMapper;
import com.ruoyi.busi.service.ISysOrgService;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;

/**
 * 司法行政机构 Service 实现
 *
 * @author ruoyi
 */
@Service
public class SysOrgServiceImpl implements ISysOrgService
{
    @Autowired
    private SysOrgMapper sysOrgMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public List<SysOrg> selectSysOrgList(SysOrgQuery query)
    {
        applyOrgDataScope(query);
        return sysOrgMapper.selectSysOrgList(query);
    }

    @Override
    public List<SysOrgTreeSelect> selectSysOrgTree(SysOrgQuery query)
    {
        applyOrgDataScope(query);
        @SuppressWarnings("unchecked")
        List<SysOrgTreeSelect> cache = (List<SysOrgTreeSelect>) redisService.getCacheObject(BusiCacheConstants.SYS_ORG_TREE_KEY);
        if (cache != null && isEmptyQuery(query))
        {
            return cache;
        }
        List<SysOrg> orgList = sysOrgMapper.selectSysOrgList(query);
        List<SysOrg> tree = buildOrgTree(orgList);
        List<SysOrgTreeSelect> treeSelect = tree.stream().map(SysOrgTreeSelect::new).collect(Collectors.toList());
        if (isEmptyQuery(query))
        {
            redisService.setCacheObject(BusiCacheConstants.SYS_ORG_TREE_KEY, treeSelect);
        }
        return treeSelect;
    }

    @Override
    public SysOrg selectSysOrgByJgbm(String jgbm)
    {
        if (StringUtils.isEmpty(jgbm))
        {
            throw new ServiceException("机构编码不能为空");
        }
        String cacheKey = BusiCacheConstants.SYS_ORG_INFO_KEY + jgbm;
        SysOrg cache = redisService.getCacheObject(cacheKey);
        if (cache != null)
        {
            return cache;
        }
        SysOrg org = sysOrgMapper.selectSysOrgByJgbm(jgbm);
        if (org == null)
        {
            throw new ServiceException("机构不存在或已删除");
        }
        checkOrgDataScope(org.getJgbm());
        redisService.setCacheObject(cacheKey, org);
        return org;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSysOrg(SysOrgOperateVO operateVO)
    {
        if (!checkJgbmUnique(operateVO.getJgbm()))
        {
            throw new ServiceException("新增机构失败，机构编码'" + operateVO.getJgbm() + "'已存在");
        }
        if (!checkJgdmUnique(null, operateVO.getJgdm()))
        {
            throw new ServiceException("新增机构失败，机构代码'" + operateVO.getJgdm() + "'已存在");
        }
        validateParentOrg(operateVO.getSjsfxzzgjg(), operateVO.getJgbm());
        SysOrg org = convertToEntity(operateVO);
        org.setCreateBy(SecurityUtils.getUsername());
        org.setDeleted(0);
        if (org.getStatus() == null)
        {
            org.setStatus(1);
        }
        int rows = sysOrgMapper.insertSysOrg(org);
        if (rows > 0)
        {
            clearOrgCache(org.getJgbm());
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSysOrg(SysOrgOperateVO operateVO)
    {
        SysOrg dbOrg = sysOrgMapper.selectSysOrgByJgbm(operateVO.getJgbm());
        if (dbOrg == null)
        {
            throw new ServiceException("修改机构失败，机构不存在");
        }
        checkOrgDataScope(dbOrg.getJgbm());
        if (!checkJgdmUnique(operateVO.getJgbm(), operateVO.getJgdm()))
        {
            throw new ServiceException("修改机构失败，机构代码'" + operateVO.getJgdm() + "'已存在");
        }
        if (StringUtils.equals(operateVO.getJgbm(), operateVO.getSjsfxzzgjg()))
        {
            throw new ServiceException("修改机构失败，上级机构不能是自己");
        }
        validateParentOrg(operateVO.getSjsfxzzgjg(), operateVO.getJgbm());
        SysOrg org = convertToEntity(operateVO);
        org.setUpdateBy(SecurityUtils.getUsername());
        int rows = sysOrgMapper.updateSysOrg(org);
        if (rows > 0)
        {
            clearOrgCache(org.getJgbm());
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteSysOrgByJgbm(String jgbm)
    {
        SysOrg org = sysOrgMapper.selectSysOrgByJgbm(jgbm);
        if (org == null)
        {
            throw new ServiceException("删除机构失败，机构不存在");
        }
        checkOrgDataScope(jgbm);
        if (sysOrgMapper.countChildByJgbm(jgbm) > 0)
        {
            throw new ServiceException("存在下级机构，不允许删除");
        }
        int rows = sysOrgMapper.deleteSysOrgByJgbm(jgbm, SecurityUtils.getUsername());
        if (rows > 0)
        {
            clearOrgCache(jgbm);
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int changeStatus(String jgbm, Integer status)
    {
        if (status == null || (status != 0 && status != 1))
        {
            throw new ServiceException("状态值非法，仅允许0（停用）或1（正常）");
        }
        SysOrg org = sysOrgMapper.selectSysOrgByJgbm(jgbm);
        if (org == null)
        {
            throw new ServiceException("修改状态失败，机构不存在");
        }
        checkOrgDataScope(jgbm);
        if (status == 0 && sysOrgMapper.countChildByJgbm(jgbm) > 0)
        {
            throw new ServiceException("存在下级机构，不允许停用");
        }
        int rows = sysOrgMapper.updateSysOrgStatus(jgbm, status, SecurityUtils.getUsername());
        if (rows > 0)
        {
            clearOrgCache(jgbm);
        }
        return rows;
    }

    @Override
    public boolean checkJgbmUnique(String jgbm)
    {
        return sysOrgMapper.checkJgbmUnique(jgbm) == null;
    }

    @Override
    public boolean checkJgdmUnique(String jgbm, String jgdm)
    {
        SysOrg info = sysOrgMapper.checkJgdmUnique(jgdm);
        if (info == null)
        {
            return true;
        }
        return StringUtils.isNotEmpty(jgbm) && jgbm.equals(info.getJgbm());
    }

    /**
     * 构建机构树（上级编码 SJSFXZZGJG 关联）
     */
    private List<SysOrg> buildOrgTree(List<SysOrg> orgList)
    {
        List<SysOrg> returnList = new ArrayList<>();
        List<String> jgbmList = orgList.stream().map(SysOrg::getJgbm).collect(Collectors.toList());
        for (SysOrg org : orgList)
        {
            if (!jgbmList.contains(org.getSjsfxzzgjg()))
            {
                recursionFn(orgList, org);
                returnList.add(org);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = orgList;
        }
        return returnList;
    }

    private void recursionFn(List<SysOrg> list, SysOrg current)
    {
        List<SysOrg> childList = getChildList(list, current);
        current.setChildren(childList);
        for (SysOrg child : childList)
        {
            if (hasChild(list, child))
            {
                recursionFn(list, child);
            }
        }
    }

    private List<SysOrg> getChildList(List<SysOrg> list, SysOrg current)
    {
        return list.stream()
            .filter(o -> StringUtils.equals(o.getSjsfxzzgjg(), current.getJgbm()))
            .collect(Collectors.toList());
    }

    private boolean hasChild(List<SysOrg> list, SysOrg current)
    {
        return list.stream().anyMatch(o -> StringUtils.equals(o.getSjsfxzzgjg(), current.getJgbm()));
    }

    /**
     * 注入数据权限根机构编码。
     * 约定：sys_dept.leader 字段存放当前用户所属司法机构编码 JGBM。
     */
    private void applyOrgDataScope(SysOrgQuery query)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null || loginUser.getSysUser().isAdmin())
        {
            return;
        }
        String rootJgbm = resolveUserOrgJgbm(loginUser.getSysUser());
        if (StringUtils.isNotEmpty(rootJgbm))
        {
            query.setScopeRootJgbm(rootJgbm);
        }
    }

    /**
     * 校验当前用户是否有权操作目标机构
     */
    private void checkOrgDataScope(String jgbm)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null || loginUser.getSysUser().isAdmin())
        {
            return;
        }
        String rootJgbm = resolveUserOrgJgbm(loginUser.getSysUser());
        if (StringUtils.isEmpty(rootJgbm))
        {
            throw new ServiceException("无数据权限，请联系管理员配置所属机构");
        }
        SysOrgQuery query = new SysOrgQuery();
        query.setScopeRootJgbm(rootJgbm);
        query.setJgbm(jgbm);
        List<SysOrg> list = sysOrgMapper.selectSysOrgList(query);
        if (list.isEmpty())
        {
            throw new ServiceException("无权限访问该机构数据");
        }
    }

    private String resolveUserOrgJgbm(SysUser user)
    {
        if (user.getDept() != null && StringUtils.isNotEmpty(user.getDept().getLeader()))
        {
            return user.getDept().getLeader();
        }
        return null;
    }

    private SysOrg convertToEntity(SysOrgOperateVO vo)
    {
        SysOrg org = new SysOrg();
        BeanUtils.copyProperties(vo, org);
        return org;
    }

    private void validateParentOrg(String parentJgbm, String currentJgbm)
    {
        if (StringUtils.isEmpty(parentJgbm) || "0".equals(parentJgbm))
        {
            return;
        }
        if (StringUtils.equals(parentJgbm, currentJgbm))
        {
            throw new ServiceException("上级机构不能是当前机构");
        }
        SysOrg parent = sysOrgMapper.selectSysOrgByJgbm(parentJgbm);
        if (parent == null)
        {
            throw new ServiceException("上级机构不存在");
        }
    }

    private boolean isEmptyQuery(SysOrgQuery query)
    {
        return StringUtils.isEmpty(query.getJgbm())
            && StringUtils.isEmpty(query.getJgmc())
            && StringUtils.isEmpty(query.getJgdm())
            && StringUtils.isEmpty(query.getSjsfxzzgjg())
            && StringUtils.isEmpty(query.getXzqhdm())
            && query.getStatus() == null;
    }

    /**
     * 清除机构相关 Redis 缓存
     */
    private void clearOrgCache(String jgbm)
    {
        redisService.deleteObject(BusiCacheConstants.SYS_ORG_TREE_KEY);
        if (StringUtils.isNotEmpty(jgbm))
        {
            redisService.deleteObject(BusiCacheConstants.SYS_ORG_INFO_KEY + jgbm);
        }
        Collection<String> listKeys = redisService.keys(BusiCacheConstants.SYS_ORG_LIST_KEY + "*");
        if (listKeys != null && !listKeys.isEmpty())
        {
            redisService.deleteObject(listKeys);
        }
    }
}
