package com.sptg.gateway.controller.estate;

import com.baomidou.mybatisplus.plugins.Page;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.constant.SysLogConstant;
import com.sptg.common.core.entity.PublishTask;
import com.sptg.common.core.enums.Instruct;
import com.sptg.common.core.util.WebUtils;
import com.sptg.common.security.annotation.Security;
import com.sptg.common.security.enums.DataFormatEnum;
import com.sptg.common.security.service.SecurityServiceInterface;
import com.sptg.device.api.entity.Device;
import com.sptg.device.api.feigns.DeviceFeign;
import com.sptg.device.api.feigns.MsgPublishFeign;
import com.sptg.estate.api.constant.EstateSecurityToken;
import com.sptg.estate.api.dto.NoticePushDto;
import com.sptg.estate.api.entity.NoticePush;
import com.sptg.estate.api.entity.NoticePushDetails;
import com.sptg.estate.api.entity.NoticePushDeviceDetails;
import com.sptg.estate.api.feigns.NoticePushFeign;
import com.sptg.estate.api.feigns.ResidentialFeign;
import com.sptg.estate.api.feigns.UnitFeign;
import com.sptg.permissions.api.dto.RegionAuthorizeDto;
import com.sptg.permissions.api.entity.Account;
import com.sptg.permissions.api.entity.RegionAuthorize;
import com.sptg.permissions.api.feigns.AreaFeign;
import com.sptg.permissions.api.feigns.RegionAuthorizeFeign;
import com.sptg.statistics.api.constant.SysLogMenuConstant;
import com.sptg.statistics.api.entity.SysOperationLog;
import com.sptg.statistics.api.feigns.SysOperationLogFeign;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;
import java.util.stream.Collectors;

/**
 * title: NoticePushController
 * package: com.sptg.gateway.controller.estate
 * description: 公告发布-关网控制器
 *
 *
 *
 */
@Slf4j
@RestController
@RequestMapping("/estate/noticePush")
@RequiredArgsConstructor
public class NoticePushController {
    private final SecurityServiceInterface<Account> securityServiceInterface;
    private final NoticePushFeign noticePushFeign;
    private final ResidentialFeign residentialFeign;
    private final UnitFeign unitFeign;
    private final DeviceFeign deviceFeign;
    private final AreaFeign areaFeign;
    private final SysOperationLogFeign sysOperationLogFeign;
    private final RegionAuthorizeFeign regionAuthorizeFeign;
    private final MsgPublishFeign msgPublishFeign;


    /**
     * 功能描述:公告发布管理页面
     * @return org.springframework.web.servlet.ModelAndView
     */
    @RequestMapping("/index")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_PUSH_MANAGE)
    public ModelAndView index(){
        ModelAndView modelAndView = new ModelAndView("estate/notice-push-manage");
        return modelAndView;
    }
    /**
     * 功能描述:公告发布记录页面
     * @return org.springframework.web.servlet.ModelAndView
     */
    @RequestMapping("/record/index")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_PUSH_MANAGE)
    public ModelAndView record(){
        ModelAndView modelAndView = new ModelAndView("estate/notice-push-record");
        return modelAndView;
    }
    /**
     * 功能描述:展示公告发布管理列表
     * @param noticePushDto
     * @param page
     * @return com.sptg.common.core.beans.ResultBean<com.baomidou.mybatisplus.plugins.Page<com.sptg.estate.api.entity.NoticePush>>
     */
    @RequestMapping("/showNoticePushList")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_PUSH_MANAGE,format = DataFormatEnum.JSON)
    public ResultBean<Page<NoticePush>> showNoticePushList(NoticePushDto noticePushDto, Page<NoticePush> page){
        //查询当前用户机构位置
        Account account=securityServiceInterface.getOnLineUser();
        noticePushDto.setOrgPosition(account.getOrgPosition());
        noticePushDto.setPage(page);
        return noticePushFeign.showNoticePushList(noticePushDto);
    }
    /**
     * 功能描述:新增公告发布页面
     * @return org.springframework.web.servlet.ModelAndView
     */
    @RequestMapping("/add")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_PUSH_ADD)
    public ModelAndView add(){
        ModelAndView modelAndView = new ModelAndView("estate/notice-push-add");
        return modelAndView;
    }
    /**
     * 功能描述:添加公告发布
     * @param noticePush
     * @return com.sptg.common.core.beans.ResultBean<java.lang.Boolean>
     */
    @RequestMapping("/addNoticePush")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_PUSH_ADD,format = DataFormatEnum.JSON)
    public ResultBean<Long> addNoticePush(NoticePush noticePush){
        //日志事件
        int  operationEvent = SysLogConstant.ALTER_EVENT;
        NoticePush oldObj = new NoticePush();
        //新增时
        if(noticePush.getId()==null) {
            //查询当前用户机构
            Account account = securityServiceInterface.getOnLineUser();
            Long rootOrgId = account.getRootOrgId();
            Long orgId = account.getOrgId();
            noticePush.setOrgId(orgId);
            noticePush.setRootOrgId(rootOrgId);
            noticePush.setOrgPosition(account.getOrgPosition());
            noticePush.setCreateAccountName(account.getLoginName());
            noticePush.setCreateAccountId(account.getId());
            //发布状态
            noticePush.setPushStatus(OperationConstant.ONE);
            //状态
            noticePush.setStatus(OperationConstant.ZERO);
            //时间
            noticePush.setCreateDate(new Date());
            operationEvent = SysLogConstant.ADD_EVENT;
            oldObj = noticePush;
        }else{
            ResultBean<NoticePush> resultBean = this.noticePushFeign.findNoticePushById(noticePush.getId());
            if(resultBean != null && resultBean.getData() != null){
                oldObj = resultBean.getData();
            }
        }
        ResultBean<Long> resultBean = noticePushFeign.addNoticePush(noticePush);
        Long id=resultBean.getData();
        if(id!=null){
            //发布公告到MQ队列上
            pushNotice(id);
            NoticePush newObj = new NoticePush();
            if (noticePush.getId() != null){
                newObj = this.noticePushFeign.findNoticePushById(noticePush.getId()).getData();
            }
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            //登陆用户
            Account account = this.securityServiceInterface.getOnLineUser();
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ESTATE_NOTICE_PUSH_MANAGE,operationEvent,
                    WebUtils.getIp(),noticePush,account,oldObj,newObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }

    /**
     * 功能描述:单个或批量删除设备公告（下发删除公告指令）
     * @param noticePushDeviceDetailsList
     * @return com.sptg.common.core.beans.ResultBean<java.lang.Boolean>
     */
    /*@RequestMapping("/deleteNoticePush")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_PUSH_ADD,format = DataFormatEnum.JSON)
    public ResultBean<Long> addNoticePush(List<NoticePushDeviceDetails> noticePushDeviceDetailsList){
        //日志事件
        int  operationEvent = SysLogConstant.ALTER_EVENT;
        //新增时
        if(noticePush.getId()==null) {
            //查询当前用户机构
            Account account = securityServiceInterface.getOnLineUser();
            Long rootOrgId = account.getRootOrgId();
            Long orgId = account.getOrgId();
            noticePush.setOrgId(orgId);
            noticePush.setRootOrgId(rootOrgId);
            noticePush.setOrgPosition(account.getOrgPosition());
            noticePush.setCreateAccountName(account.getLoginName());
            noticePush.setCreateAccountId(account.getId());
            //发布状态
            noticePush.setPushStatus(OperationConstant.ONE);
            //状态
            noticePush.setStatus(OperationConstant.ZERO);
            //时间
            noticePush.setCreateDate(new Date());
            operationEvent = SysLogConstant.ADD_EVENT;
        }
        ResultBean<Long> resultBean = noticePushFeign.addNoticePush(noticePush);
        Long id=resultBean.getData();
        if(id!=null){
            //发布公告到MQ队列上
            pushNotice(id);
            *//*---------------------------------------------------记录日志--------------------------------------------------------*//*
            //登陆用户
            Account account = this.securityServiceInterface.getOnLineUser();
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ESTATE_NOTICE_PUSH_MANAGE,operationEvent,
                    WebUtils.getIp(),noticePush,account);
            sysOperationLogFeign.info(sysOperationLog);
            *//*------------------------------------------------------------------------------------------------------------------*//*
        }
        return resultBean;
    }*/
    /**
     * 功能描述:修改/详细页面
     * @param id
     * @return org.springframework.web.servlet.ModelAndView
     */
    @GetMapping(value = "/findNoticePushById/{id}")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_MANAGE)
    public ModelAndView findNoticeById(@PathVariable(value = "id") long id){
        ModelAndView modelAndView = new ModelAndView("estate/notice-push-detail");
        ResultBean<NoticePush> resultBean=noticePushFeign.findNoticePushById(id);
        NoticePush noticePush=resultBean.getData();
        //发布类型{ 1 ：按小区发布，2：按单元发布，3：按设备发布，4：按区域发布}
        Integer pushType = noticePush.getPushType();
        List<NoticePushDetails> noticePushDetailsList = noticePush.getNoticePushDetailsList();
        if(noticePushDetailsList!=null){
            List<Long> fkIds = new ArrayList<>(noticePushDetailsList.size());
            noticePushDetailsList.forEach(noticePushDetails ->{
                fkIds.add(noticePushDetails.getFkId());
            });
            List objects = null;
            //发布类型{ 1 ：按小区发布，2：按单元发布，3：按设备发布，4：按区域发布}
            if(pushType==1){
                 objects = residentialFeign.getByOrgIdList(fkIds);
            }else if(pushType==2){
                objects = unitFeign.getListByIdList(fkIds);
            }else if(pushType==3){
                objects =deviceFeign.getListByIds(fkIds);
            }else if(pushType==4){
                objects = areaFeign.getListByIds(fkIds);
            }
            modelAndView.addObject("objects",objects);
        }
        modelAndView.addObject("bean",noticePush);
        return modelAndView;
    }
    @GetMapping(value = "/cancelNoticePush/{id}")
    @Security(token = EstateSecurityToken.ESTATE_NOTICE_MANAGE,format = DataFormatEnum.JSON)
    public ResultBean<Boolean> cancelNoticePush(@PathVariable(value = "id") long id){
        ResultBean<NoticePush> oldObj = this.noticePushFeign.findNoticePushById(id);
        ResultBean<Boolean>  resultBean=noticePushFeign.cancelNoticePush(id);
        boolean result=resultBean.getData();
        if(result){
            /*---------------------------------------------------记录日志--------------------------------------------------------*/
            NoticePush noticePush=new NoticePush();
            noticePush.setId(id);
            //登陆用户
            Account account = this.securityServiceInterface.getOnLineUser();
            SysOperationLog sysOperationLog=new SysOperationLog(SysLogMenuConstant.ESTATE_NOTICE_PUSH_MANAGE,SysLogConstant.ALTER_EVENT,
                    WebUtils.getIp(),"公告发布撤回",noticePush,account,oldObj);
            sysOperationLogFeign.info(sysOperationLog);
            /*------------------------------------------------------------------------------------------------------------------*/
        }
        return resultBean;
    }


    /*----------------------------------------------------内部方法--------------------------------------------------------------*/
    /*-------------------------------------------------------------------------------------------------------------------------*/

    private void pushNotice(long noticePushId){
        //获取发布的公告
        ResultBean<NoticePush> resultBean = noticePushFeign.findNoticePushById(noticePushId);
        NoticePush noticePush = resultBean.getData();
        if(noticePush != null){
            String pushTarget = noticePush.getPushTarget();
            //是否发布渠道设备
            if(StringUtils.isNotBlank(pushTarget)&&pushTarget.contains(OperationConstant.ZERO+"")){
                try {
                    //发布状态--发布成功
                    noticePush.setPushStatus(OperationConstant.ONE);
                    //公告发布详情
                    List<NoticePushDetails> noticePushDetailsList = noticePush.getNoticePushDetailsList();
                    // 获取关联外键Id列表
                    List<Long> fkIdList = noticePushDetailsList.stream().map(NoticePushDetails::getFkId).collect(Collectors.toList());
                    noticePush.setNoticePushDetailsList(null);
                    noticePush.setNotice(null);

                    List<Long> deviceIdList;
                    switch (noticePush.getPushType()) {
                        //  小区发布
                        case 1:
                            deviceIdList = this.getDeviceIdByXqs(fkIdList);
                            break;
                        //  单元发布
                        case 2:
                            deviceIdList = this.getDeviceIdByUnits(fkIdList);
                            break;
                        //  设备发布
                        case 3:
                            deviceIdList = fkIdList;
                            break;
                        //  区域发布
                        case 4:
                            deviceIdList = this.getDeviceIdByRegions(fkIdList,noticePush.getOrgPosition());
                            break;
                        default:
                            deviceIdList = new ArrayList<>(0);
                            break;
                    }

                    PublishTask publishTask = new PublishTask(noticePush.getId(), Instruct.add_notice,noticePush,deviceIdList);
                    //  任务类型：{ 1：广告，2：策略，3：公告 }
                    publishTask.setTaskType(3);
                    Map<String,String> map = new HashMap<>();
                    this.msgPublishFeign.publishTask(publishTask,map);

                    //发布时间
                    noticePush.setPushCount((long)deviceIdList.size());
                    noticePush.setPushDate(new Date());
                } catch (Exception e) {
                    //发布失败
                    noticePush.setPushStatus(OperationConstant.MINUS_ONE);
                    noticePush.setRemark("网络异常");
                    log.error(e.getMessage(),e);
                }
                //修改发布状态
                noticePushFeign.updateNoticePushById(noticePush);
            }
        }
    }

    private List<Long> getDeviceIdByRegions(List<Long> fkIdList,String position){
        List<Long> xqIdList = new ArrayList<>();
        PageBean<RegionAuthorize, RegionAuthorizeDto> pageBean = new PageBean<>();
        pageBean.setSize(100);
        RegionAuthorizeDto dto = new RegionAuthorizeDto();
        dto.setUserOrgPosition(position);
        dto.setAreaIdList(fkIdList);
        pageBean.setDto(dto);
        int pageNo = 0;
        while (true){
            ++ pageNo;
            pageBean.setCurrent(pageNo);
            //  得到授权小区列表
            Page<RegionAuthorize> page = this.regionAuthorizeFeign.pagingQuery(pageBean);
            if (page.getRecords().size() == 0){
                break;
            }
            page.getRecords().forEach(authorize -> xqIdList.add(authorize.getXqId()));
        }
        return this.getDeviceIdByXqs(xqIdList);
    }

    private List<Long> getDeviceIdByXqs(List<Long> fkIdList){
        List<Long> deviceIdList = new ArrayList<>();
        fkIdList.forEach(xqId -> {
            List<Device> deviceList = this.deviceFeign.getListByXqId(xqId);
            deviceList.forEach(device -> deviceIdList.add(device.getId()));
        });
        return deviceIdList;
    }

    private List<Long> getDeviceIdByUnits(List<Long> fkIdList){
        List<Device> deviceList = this.deviceFeign.getListByUnitIds(fkIdList);
        return deviceList.stream().map(Device::getId).collect(Collectors.toList());
    }
}
