package com.sptg.permissions.biz.controller;

import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.constant.SymbolConstant;
import com.sptg.common.core.util.CommonUtil;
import com.sptg.permissions.api.dto.OrgDto;
import com.sptg.permissions.api.entity.Organization;
import com.sptg.permissions.api.enums.PermissionsEnum;
import com.sptg.permissions.api.feigns.OrgFeign;
import com.sptg.permissions.biz.service.OrgServiceInterface;
import com.sptg.permissions.biz.stream.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

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

/**
 * title: OrgController
 * package: com.sptg.permissions.biz.controller
 * description: 机构控制器
 *
 *
 *
 */
@RestController
@RequiredArgsConstructor
public class OrgController implements OrgFeign {

    private final OrgServiceInterface orgServiceInterface;
    private final RedisTemplate<String,String> redisTemplate;
    private final OrgDisableProduceInterface orgDisableProduceInterface;
    private final OrgDeleteProduceInterface orgDeleteProduceInterface;
    private final XqAddProduceInterface xqAddProduceInterface;
    private final OrgModifyNameProduceInterface orgModifyNameProduceInterface;
    private final OrgTransferProduceInterface orgTransferProduceInterface;
    private final static String IMPORT_CACHE_ORG_CODE = "sptg:import:org:code";

    @Override
    @GetMapping(value = "/org/get/{id}")
    public Organization getOrgById(@PathVariable(value = "id")Long id) {
        return this.orgServiceInterface.selectById(id);
    }

    @Override
    @PostMapping(value = "/org/pagingQuery")
    public Page<Organization> pagingQuery(@RequestBody PageBean<Organization,OrgDto> pageBean) {
        OrgDto dto = pageBean.getDto();
        if (null != dto.getId()){
            Organization organization = this.orgServiceInterface.selectById(dto.getId());
            //  判断非空,并校验权限
            if (null == organization || !organization.getPosition().startsWith(dto.getPosition())){
                return new Page<>();
            }
            dto.setPosition(organization.getPosition());
        }
        return this.orgServiceInterface.showOrgList(pageBean);
    }

    @Override
    @PostMapping(value = "/org/getSubListByPid")
    public List<Organization> getSubListByPid(@RequestBody OrgDto dto) {
        Wrapper<Organization> wrapper = new EntityWrapper<>();
        wrapper.eq("l_pid",dto.getPid());
        if(OperationConstant.ZERO < dto.getIsShowFlag()){
            wrapper.notIn("i_flag",dto.getIsShowFlag());
        }
        wrapper.like("s_position",dto.getPosition(), SqlLike.RIGHT);
        wrapper.orderBy("i_org_type", true);
        return this.orgServiceInterface.selectList(wrapper);
    }

    @Override
    @PostMapping(value = "/org/updateIsEnable")
    public ResultBean<Boolean> updateIsEnable(@RequestBody OrgDto dto) {
        //  获取修改前的机构信息
        Organization dbOrg = this.orgServiceInterface.selectById(dto.getId());
        Assert.notNull(dbOrg,"机构Id不存在");
        //  权限校验
        if (!dbOrg.getPosition().startsWith(dto.getPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //  判断是否需要修改
        if (dbOrg.getIsEnable().equals(dto.getIsEnable())){
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        //  判断是否禁用机构
        boolean result;
        if (!dto.getIsEnable().equals(OperationConstant.ONE)){
            dbOrg.setIsEnable(OperationConstant.TWO);
            result = this.orgServiceInterface.updateById(dbOrg);
            if (result){
                //  通知队列禁用该机构下所有子机构
                Message<Long> build = MessageBuilder.withPayload(dto.getId()).build();
                this.orgDisableProduceInterface.output().send(build);
            }
        }else {
            //  判断父机构是否被禁用
            Organization parent = this.orgServiceInterface.selectById(dbOrg.getPid());
            if (parent.getIsEnable().equals(OperationConstant.ONE)) {
                dbOrg.setIsEnable(OperationConstant.ONE);
                result = this.orgServiceInterface.updateById(dbOrg);
            }else {
                return new ResultBean<>(PermissionsEnum.ORGANIZATION_PARENT_DISABLE);
            }
        }
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @PostMapping(value = "/org/deleteEntity")
    @Transactional(rollbackFor = Throwable.class)
    @LcnTransaction
    public ResultBean<Boolean> deleteEntity(@RequestBody OrgDto dto) {
        //  获取修改前的机构信息
        Organization dbOrg = this.orgServiceInterface.selectById(dto.getId());
        Assert.notNull(dbOrg,"机构不存在");
        //  权限校验
        if (!dbOrg.getFlag().equals(dto.getFlag()) || !dbOrg.getPosition().startsWith(dto.getPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //  判断此机构下是否有子机构
        if (dbOrg.getClientCount() > OperationConstant.ZERO){
            return new ResultBean<>(PermissionsEnum.ORGANIZATION_HAVE_CLIENT);
        }
        //  标记为删除状态
        dbOrg.setStatus(dto.getStatus());
        //  获取上级节点
        Organization parent = this.orgServiceInterface.selectById(dbOrg.getPid());
        //  子节点数量 -1
        parent.setClientCount(parent.getClientCount() - 1);
        if (dbOrg.getFlag() == OperationConstant.THREE){
            parent.setDeptCount(parent.getDeptCount() - 1);
        }
        //  生成需要修改的列表
        List<Organization> organizationList = new ArrayList<>(2);
        organizationList.add(dbOrg);
        organizationList.add(parent);
        boolean result = this.orgServiceInterface.updateBatchById(organizationList);
        if (result){
            //  通知队列机构已被删除
            Message<Organization> build = MessageBuilder.withPayload(dbOrg).build();
            this.orgDeleteProduceInterface.output().send(build);
        }
        this.deleteCache(dbOrg);
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @PostMapping(value = "/org/selectListByLikeName")
    public List<Organization> selectListByLikeName(@RequestBody OrgDto dto) {
        Wrapper<Organization> wrapper = new EntityWrapper<>();
        wrapper.like("s_position",dto.getPosition(), SqlLike.RIGHT);
        if (StringUtils.hasText(dto.getName())){
            wrapper.like("s_name",dto.getName(),SqlLike.DEFAULT);
        }
        //  判断是否需要过滤某些机构
        if (!StringUtils.isEmpty(dto.getExcludePosition())){
            wrapper.notLike("s_position",dto.getExcludePosition(), SqlLike.RIGHT);
        }
        //  查询指定类型
        if (null != dto.getFlag()){
            wrapper.eq("i_flag",dto.getFlag());
        }
        if (dto.getOrgType() != null){
            wrapper.eq("i_org_type",dto.getOrgType());
        }
        //是否是下拉列表

        if (dto.getIsSelect()){
            wrapper.last("limit 10");
        }
        return this.orgServiceInterface.selectList(wrapper);
    }

    @Override
    @PostMapping(value = "/org/addEntity")
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Organization> addEntity(@RequestBody OrgDto dto) {
        //  获取父级别机构信息
        Organization parent = this.orgServiceInterface.selectById(dto.getPid());
        Assert.notNull(parent,"机构父级Id不存在");
        //  校验权限
        if (!dto.getPosition().startsWith(parent.getPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
//        if (dto.getFlag() == 1){
//            //  名称去重
//            boolean isExist = this.orgServiceInterface.checkNameIsExist(dto.getName());
//            Assert.isTrue(!isExist,"机构名称已经存在");
//        }
        //  是否禁用
        dto.setIsEnable(parent.getIsEnable());
        //  上级机构名称
        dto.setParentName(parent.getName());
        //  层级数量
        dto.setLayerNumber(parent.getLayerNumber() + 1);
        //  机构类别
        if (null == dto.getOrgType()){
            dto.setOrgType(parent.getOrgType());
        }
        //  保存数据
        if (this.orgServiceInterface.insert(dto)){
            //  设置跟机构Id,position字段
            if (parent.getRootOrgId() == OperationConstant.ONE){
                dto.setRootOrgId(dto.getId());
            }else {
                dto.setRootOrgId(parent.getRootOrgId());
            }
            //  设置存储位置
            String position = parent.getPosition() + dto.getId() + SymbolConstant.BACK_SLASH;
            dto.setPosition(position);
            //  设置编号
            String code = dto.getCode() + CommonUtil.autoZeroFilling(5, dto.getId());
            dto.setCode(code);
            this.orgServiceInterface.updateById(dto);
            //  父级的子节点数量+1
            parent.setClientCount(parent.getClientCount() + 1);
            //  判断是否为部门
            if(dto.getFlag() != null){
                switch (dto.getFlag()){
                    //  小区
                    case OperationConstant.TWO:
                        Message<OrgDto> build = MessageBuilder.withPayload(dto).build();
                        this.xqAddProduceInterface.output().send(build);
                        break;
                    //  部门
                    case OperationConstant.THREE:
                        parent.setDeptCount(parent.getDeptCount() + 1);
                        break;
                    default: break;
                }
                this.orgServiceInterface.updateById(parent);
                return new ResultBean<>(ResultEnum.SUCCESS,dto);
            }else {
                return new ResultBean<>(ResultEnum.SUCCESS,dto);
            }


        }
        return new ResultBean<>(ResultEnum.ERROR);
    }


    @Override
    @PostMapping(value = "/org/editEntity")
    @Transactional(rollbackFor = Throwable.class)
    @LcnTransaction
    public ResultBean<Boolean> editEntity(@RequestBody OrgDto dto) {
        Organization dbOrg = this.orgServiceInterface.selectById(dto.getId());
        Assert.notNull(dbOrg,"机构Id不存在");
        //  权限校验
        if (!dbOrg.getFlag().equals(dto.getFlag()) || !dbOrg.getPosition().startsWith(dto.getPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        if (StringUtils.hasText(dto.getName()) && !dto.getName().equals(dbOrg.getName()) && dto.getFlag() == 1){
            //  名称去重
            boolean isExist = this.orgServiceInterface.checkNameIsExist(dto.getName());
            Assert.isTrue(!isExist,"机构名称已经存在");
        }
        //  不修改上级节点和状态
        dto.setPid(null);
        dto.setPosition(null);
        dto.setIsEnable(null);
        //  保存修改
        boolean result = this.orgServiceInterface.updateById(dto);
        if (result){
            //  判断是否修改了机构名称
            if (!dbOrg.getName().equals(dto.getName())){
                //  通知队列修改机构名称
                Message<OrgDto> build = MessageBuilder.withPayload(dto).build();
                this.orgModifyNameProduceInterface.output().send(build);
            }
        }
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @PostMapping(value = "/org/updatePid")
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Boolean> updatePid(@RequestBody OrgDto dto) {
        Organization dbOrg = this.orgServiceInterface.selectById(dto.getId());
        Assert.notNull(dbOrg,"机构Id不存在");
        //  权限校验
        if (!dbOrg.getPosition().startsWith(dto.getPosition())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //  获取新上级机构信息
        Organization parent = this.orgServiceInterface.selectById(dto.getPid());
        Assert.notNull(parent,"机构父级Id不存在");
        //  校验机构类型
        Assert.isTrue(parent.getOrgType().equals(1) || dbOrg.getOrgType().equals(parent.getOrgType()),"迁移失败,机构类型不一致");
        parent.setClientCount(parent.getClientCount() + 1);
        //  获取原上级机构信息
        Organization oldParent = this.orgServiceInterface.selectById(dbOrg.getPid());
        oldParent.setClientCount(oldParent.getClientCount() - 1);
        if (dbOrg.getFlag() == OperationConstant.THREE){
            parent.setDeptCount(parent.getDeptCount() + 1);
            oldParent.setDeptCount(oldParent.getDeptCount() - 1);
        }
        //  设置根机构Id
        if (parent.getRootOrgId() == OperationConstant.ONE){
            dto.setRootOrgId(parent.getId());
        }else {
            dto.setRootOrgId(parent.getRootOrgId());
        }
        dto.setOrgPosition(dbOrg.getPosition());
        //  设置position,父级名称,层级
        dto.setPosition(parent.getPosition() + dto.getId() + SymbolConstant.BACK_SLASH);
        dto.setParentName(parent.getName());
        dto.setLayerNumber(parent.getLayerNumber() + 1);
        //  是否可用
        dto.setIsEnable(parent.getIsEnable());
        //  获取子节点列表
        String position = dbOrg.getPosition();
        List<Organization> subOrgList = this.orgServiceInterface.selectByPosition(position);
        int layerCha = dto.getLayerNumber() - dbOrg.getLayerNumber();
        subOrgList.forEach(org -> {
            org.setIsEnable(dto.getIsEnable());
            org.setPosition(org.getPosition().replace(dbOrg.getPosition(), dto.getPosition()));
            org.setLayerNumber(org.getLayerNumber() + layerCha);
        });
        //  生成需要修改的机构列表
        List<Organization> organizationList = new ArrayList<>(subOrgList);
        organizationList.add(dto);
        organizationList.add(parent);
        organizationList.add(oldParent);
        boolean result = this.orgServiceInterface.updateBatchById(organizationList);
        if (result){
            //  通知队列修改关联表中的position字段
            Message<OrgDto> build = MessageBuilder.withPayload(dto).build();
            this.orgTransferProduceInterface.output().send(build);
        }
        return new ResultBean<>(ResultEnum.SUCCESS,result);
    }

    @Override
    @GetMapping(value = "/org/getOrgByCode/{code}")
    public Organization getOrgByCode(@PathVariable(value = "code")String code) {
        Wrapper<Organization> wrapper = new EntityWrapper<>();
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        wrapper.eq("s_code",code);
        return this.orgServiceInterface.selectOne(wrapper);
    }

    @Override
    @PostMapping(value = "/org/selectListByCondition")
    public List<Organization> selectListByCondition(@RequestBody OrgDto dto) {
        Wrapper<Organization> wrapper = new EntityWrapper<>();

        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);

        wrapper.like("s_position",dto.getPosition(), SqlLike.RIGHT);
        // 2:社区机构->查询小区  1:小区管理->只需查询小区以上机构 3:单元管理->查询社区机构
        if(null != dto.getFlag()){
            wrapper.eq("i_flag",dto.getFlag());
        }
        if (null != dto.getOrgType()){
            wrapper.eq("i_org_type", dto.getOrgType());
        }
        if (dto.getName() != null){
            wrapper.like("s_name",dto.getName(),SqlLike.DEFAULT);
        }
        if (dto.getIsSelect()){
            wrapper.last("limit 10");
        }
        System.out.println("--i_org_type--" + dto.getOrgType());
        wrapper.orderBy("t_create_date",true);
        return this.orgServiceInterface.selectList(wrapper);
    }

    @Override
    @PostMapping(value = "/org/getListByIds")
    public List<Organization> getListByIds(@RequestBody List<Long> idList) {
        List<Organization> list = new ArrayList<>(idList.size());
        idList.forEach(id -> {
            Organization org = this.orgServiceInterface.selectById(id);
            if (null != org){
                list.add(org);
            }
        });
        return list;
    }

    @Override
    @PostMapping(value = "/org/selectCount")
    public Integer selectCount(@RequestBody OrgDto dto) {
        return this.orgServiceInterface.selectCount(dto);
    }

    @Override
    @PostMapping(value = "/org/updateEntity")
    public boolean updateEntity(@RequestBody Organization org) {
        return this.orgServiceInterface.updateById(org);
    }

    @Override
    @GetMapping(value = "/org/{oldId}/{orgType}")
    public Organization getByOldIdAndType(
            @PathVariable(value = "oldId") String oldId,
            @PathVariable(value = "orgType") String orgType) {
        Wrapper<Organization> wrapper = new EntityWrapper<>();
        wrapper.eq("old_id",oldId);
        if (!"0".equals(orgType)) {
            wrapper.eq("i_org_type", orgType);
        }
        return this.orgServiceInterface.selectOne(wrapper);
    }

    @Override
    public boolean checkNameIsExist(String orgName) {
        return this.orgServiceInterface.checkNameIsExist(orgName);
    }

    /* -------------------------------------------------- 内部方法 -------------------------------------------------- */
    /* -------------------------------------------------------------------------------------------------------------- */
    /**
     * 功能描述:删除缓存
     * @param org 机构
     *
     *
     */
    private void deleteCache(Organization org){
        HashOperations<String, String, String> hashOperations = this.redisTemplate.opsForHash();
        String hashKey = org.getCode();
        String json = hashOperations.get(IMPORT_CACHE_ORG_CODE,hashKey);
        if (!StringUtils.isEmpty(json)) {
            hashOperations.delete(IMPORT_CACHE_ORG_CODE,hashKey);
        }
    }
}
