package com.sptg.estate.biz.receiver;

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.sptg.common.core.beans.PageBean;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.entity.PublishTask;
import com.sptg.common.core.enums.Instruct;
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.entity.NoticePush;
import com.sptg.estate.api.entity.NoticePushDetails;
import com.sptg.estate.biz.service.NoticePushDetailsServiceInterface;
import com.sptg.estate.biz.service.NoticePushServiceInterface;
import com.sptg.estate.biz.stream.SyncNoticeDataDeviceReceiverInterface;
import com.sptg.permissions.api.dto.RegionAuthorizeDto;
import com.sptg.permissions.api.entity.RegionAuthorize;
import com.sptg.permissions.api.feigns.DeviceAuthorizeFeign;
import com.sptg.permissions.api.feigns.RegionAuthorizeFeign;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.stereotype.Component;

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

/**
 * title: SyncNoticeDataDeviceReceiver
 * description: 同步设备公告
 *
 *
 *
 */
@Component
@Slf4j
@RequiredArgsConstructor
@EnableBinding(value = { SyncNoticeDataDeviceReceiverInterface.class})
public class SyncNoticeDataDeviceReceiver {

    private final DeviceFeign deviceFeign;
    private final DeviceAuthorizeFeign deviceAuthorizeFeign;
    private final NoticePushServiceInterface noticePushServiceInterface;
    private final RegionAuthorizeFeign regionAuthorizeFeign;
    private final MsgPublishFeign msgPublishFeign;

    @StreamListener(value = SyncNoticeDataDeviceReceiverInterface.INPUT)
    public void input(String serialNumber){
        if (null == serialNumber){
            return;
        }
        //  获取设备授权的机构列表
        List<String> orgPositionList = this.deviceAuthorizeFeign.getDeviceAuthorizeOrgList(serialNumber);
        if (null == orgPositionList || orgPositionList.size() <= 0){
            return;
        }
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(serialNumber);
        if (null  == device){
            return;
        }
        //  分页获取公告列表
        int pageNum = 1;
        int pageSize = 100;
        Page<NoticePush> page = new Page<>();
        page.setSize(pageSize);
        /*
            构建查询条件：
                1.查询授权机构下发的所有公告记录
                2.过滤已过期数据
                3.只查询发布成功的数据
                4.过滤针对单台设备发布的数据
                5.目标渠道含设备的公告
         */
        Wrapper<NoticePush> wrapper = new EntityWrapper<>();
//        wrapper.in("s_org_position", orgPositionList);
        wrapper.gt("t_end_date",new Date());
        wrapper.eq("i_push_status",1);
        wrapper.notIn("i_push_type",3);
        wrapper.like("s_push_target","0", SqlLike.DEFAULT);
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < orgPositionList.size(); i++){
            sb.append("INSTR(\'" + orgPositionList.get(i) +" \', s_org_position" + ")");
//            wrapper.where("INSTR(\'" + orgPositionList.get(i) +" \', s_org_position" + ")");
            if(i < orgPositionList.size() - 1){
//                wrapper.or();
                sb.append(" or ");
            }
        }
        if(sb.length() > 0){
            String sql = "(" + sb.toString() + ")";
            wrapper.where(sql);
        }
        while (true){
            page.setCurrent(pageNum);
            Page<NoticePush> resultPage = this.noticePushServiceInterface.selectPage(page, wrapper);
            if (resultPage.getRecords().size() > 0){
                //  推送任务
                resultPage.getRecords().forEach(notice -> this.pushTask(notice,device));
            }
            if (resultPage.getRecords().size() < pageSize){
                //  结束循环
                break;
            }
            ++ pageNum;
        }

    }

    private final NoticePushDetailsServiceInterface noticePushDetailsServiceInterface;

    /**
     * 同步公告时候，只会同步那些按照小区、单元、区域发布的公告，按照设备发布的公告不会去同步。
     * @param noticePush
     * @param device
     */
    private void pushTask(NoticePush noticePush,Device device){
        List<NoticePushDetails> detailsList = this.noticePushDetailsServiceInterface.getListByNoticePushId(noticePush.getId());
        List<Long> fkIdList = detailsList.stream().map(NoticePushDetails::getFkId).collect(Collectors.toList());
        List<Long> deviceIdList;
        switch (noticePush.getPushType()){
            //  小区发布
            case 1:
                if (!fkIdList.contains(device.getXqId())){
                    return;
                }
                deviceIdList = this.getDeviceIdByXqs(fkIdList);
                break;
            //  单元发布
            case 2:
                if (!fkIdList.contains(device.getUnitId())){
                    return;
                }
                deviceIdList = this.getDeviceIdByUnits(fkIdList);
                break;
            //  区域发布
            case 4:
                if (!fkIdList.contains(Long.parseLong(device.getRegionProvince())) &&
                        !fkIdList.contains(Long.parseLong(device.getRegionCity())) &&
                        !fkIdList.contains(Long.parseLong(device.getRegionArea()))){
                    return;
                }
                deviceIdList = this.getDeviceIdByRegions(fkIdList,noticePush.getOrgPosition());
                break;
            default: return;
        }

        PublishTask publishTask = new PublishTask(noticePush.getId(), Instruct.add_notice,noticePush,deviceIdList);
        publishTask.setTaskType(OperationConstant.THREE);
        Map<String,String> map = new HashMap<>();
        this.msgPublishFeign.publishTask(publishTask,map);
    }


    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());
    }

}
