package com.yeejoin.amos.boot.module.jcs.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.common.api.mapper.StationInfoMapper;
import com.yeejoin.amos.boot.module.common.biz.service.impl.FirefightersServiceImpl;
import com.yeejoin.amos.boot.module.jcs.api.dto.SignDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.SinStaticDto;
import com.yeejoin.amos.boot.module.jcs.api.entity.Sign;
import com.yeejoin.amos.boot.module.jcs.api.mapper.SignMapper;
import com.yeejoin.amos.boot.module.jcs.api.service.ISignService;
import com.yeejoin.amos.component.rule.config.RuleConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.text.NumberFormat;
import java.time.LocalDate;
import java.util.*;

/**
 * 打卡记录服务实现类
 *
 * @author system_generator
 * @date 2022-08-15
 */
@Slf4j
@Service
@EnableScheduling
public class SignServiceImpl extends BaseService<SignDto, Sign, SignMapper> implements ISignService {

    @Autowired
    FirefightersServiceImpl iFirefightersService;
    @Autowired
    private EmqKeeper emqKeeper;
    @Value("${mqtt.topic.person.sign}")
    private String personSign;
    @Value("${mqtt.topic.person.sign.zxj:sign/data/synZxj}")
    private String personSignZxj;
    @Autowired
    private StationInfoMapper stationInfoMapper;

    /**
     * 分页查询
     */
    public Page<SignDto> queryForSignPage(Page<SignDto> page) {
        return this.queryForPage(page, null, false);
    }

    /**
     * 分页查询
     */
    public IPage<SignDto> queryForSignPageByMapper(IPage<SignDto> page, SignDto dto) {
        return this.baseMapper.queryForPage(page, dto);
    }

    /**
     * 分页查询
     */
    public IPage<SinStaticDto> queryForSignStaticPageByMapper(IPage<SinStaticDto> page, SinStaticDto dto) {
        IPage<SinStaticDto> sinStaticDtoIPage = this.baseMapper.queryStaticForPage(page, dto);
        NumberFormat numberFormat = NumberFormat.getNumberInstance();
        numberFormat.setMaximumFractionDigits(2);

        sinStaticDtoIPage.getRecords().stream().forEach(e -> {

            e.setAttendance(e.getSignNum() + "/" + e.getPersonOfDay());
        });

        return sinStaticDtoIPage;
    }

    public List<Map<String, Object>> queryPeopleInfo(SinStaticDto dto) {
        List<Map<String, Object>> res = this.baseMapper.queryPeopleInfo(dto);
        return res;
    }

    /**
     * 列表查询 示例
     */
    public List<SignDto> queryForSignList() {
        return this.queryForList("", false);
    }

    @Override
    public Boolean hasSign(String type, String date, String userId) {
        QueryWrapper<Sign> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("date", date);
        if (StringUtils.isNotEmpty(type)) {
            queryWrapper.eq("type", type);
        }
        if (StringUtils.isNotEmpty(userId)) {
            queryWrapper.eq("user_id", userId);
        }
        List<Sign> signs = this.baseMapper.selectList(queryWrapper);

        if (StringUtils.isEmpty(type) && signs.size() != 2) {
            return true;
        } else {
            if (StringUtils.isNotEmpty(type) && signs.size() == 1) {
                return true;
            }
            return false;
        }
    }

    @Override
    public Map<String, Object> getSignStatistic(String userId, String bizOrgCode) {
        // 人员缺卡统计暂无法统计，只知道person_of_day需要打卡总人数，但是打一次卡和哪些人打卡无法获取，此处返回了默认值
        //        this.baseMapper.getSignStatistic(bizOrgCode, userId);
        Map<String, Object> map = new HashMap<>();
        map.put("totalNum", 50);
        map.put("loss", 4);
        return map;
    }

    @Override
    public Boolean saveSign(SignDto dot) {
        Sign sign = new Sign();
        Map<String, Object> bizOrgCodeAndBizOrgName = iFirefightersService.getCompanyName(dot.getBizOrgCode());
        int num = this.baseMapper.queryPersonNum(bizOrgCodeAndBizOrgName.get("bizOrgCode").toString());
        Bean.copyExistPropertis(dot, sign);
        sign.setPersonOfDay(String.valueOf(num));
        boolean save = this.save(sign);
        // 发送mqtt 消息 同步人员打卡数据
        if (save) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("bizOrgName", ObjectUtils.isEmpty(sign.getBizOrgName()) ? "" : sign.getBizOrgName());
            map.put("bizOrgCode", ObjectUtils.isEmpty(sign.getBizOrgCode()) ? "" : sign.getBizOrgCode());
            map.put("orgCode", ObjectUtils.isEmpty(sign.getOrgCode()) ? "" : sign.getOrgCode());
            map.put("signUserName", ObjectUtils.isEmpty(sign.getName()) ? "" : sign.getName());
            map.put("jobTitle", ObjectUtils.isEmpty(sign.getJobTitle()) ? "" : sign.getJobTitle());
            map.put("userId", ObjectUtils.isEmpty(sign.getSignUserId()) ? "" : sign.getSignUserId());
            map.put("signDate", ObjectUtils.isEmpty(sign.getSignTime()) ? "" : sign.getSignTime());
            map.put("recUserId", ObjectUtils.isEmpty(sign.getRecUserId()) ? "" : sign.getRecUserId());
            map.put("recUserName", ObjectUtils.isEmpty(sign.getRecUserName()) ? "" : sign.getRecUserName());
            map.put("sequenceNbr", ObjectUtils.isEmpty(sign.getRecUserName()) ? "" : sign.getSequenceNbr());
            String json = JSON.toJSONString(map, SerializerFeature.PrettyFormat,
                    SerializerFeature.WriteMapNullValue);
            try {
                emqKeeper.getMqttClient().publish(personSign, json.getBytes(), RuleConfig.DEFAULT_QOS, false);
                map.put("personOfDay", ObjectUtils.isEmpty(sign.getPersonOfDay()) ? "" : sign.getPersonOfDay());
                map.put("type", ObjectUtils.isEmpty(sign.getType()) ? "" : sign.getType());
                map.put("photos", ObjectUtils.isEmpty(sign.getPhotos()) ? "" : sign.getPhotos());
                map.put("remarks", ObjectUtils.isEmpty(sign.getRemarks()) ? "" : sign.getRemarks());
                map.put("date", ObjectUtils.isEmpty(sign.getDate()) ? "" : sign.getDate());
                map.put("recDate", ObjectUtils.isEmpty(sign.getRecDate()) ? "" : sign.getRecDate());
                map.put("isDelete", ObjectUtils.isEmpty(sign.getIsDelete()) ? "" : sign.getIsDelete());
                map.put("source", ObjectUtils.isEmpty(sign.getSource()) ? "" : sign.getSource());
                String json1 = JSON.toJSONString(map, SerializerFeature.PrettyFormat,
                        SerializerFeature.WriteMapNullValue);
                // 发送emq消息转kafka
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("topic", personSign);
                jsonObject.put("data", json);
                emqKeeper.getMqttClient().publish("emq.sign.created", jsonObject.toString().getBytes(), 1, false);

                // 发送emq消息转kafka 同步业务库打卡表
                JSONObject jsonObject1 = new JSONObject();
                jsonObject1.put("topic", personSignZxj);
                jsonObject1.put("data", json1);
                emqKeeper.getMqttClient().publish("emq.bussSign.created", jsonObject1.toString().getBytes(), 1, false);

            } catch (MqttException e) {
                log.info(String.format("发送eqm打卡消息失败：%s", e.getMessage()));
            }
        }
        return save;
    }

    /**
     * 每日计算当天打卡记录，统计至少8人出勤。。
     *
     */
    @Scheduled(cron = "${jcs.sign.cron:0 40 23 * * ?}")
    @Transactional(rollbackFor = Exception.class)
    public void jcsSignStatic() {
        log.info("开始出勤统计=========");
        List<Map<String, Object>> mapSign = this.baseMapper.querySignInfo();
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (Map<String, Object> m : mapSign) {
            // 判断至少8人出勤
            if (Integer.parseInt(m.get("num").toString()) >= 8) {
                Map<String, Object> map = new HashMap<>();
                map.put("bizOrgCode", m.get("bizOrgCode"));
                map.put("bizOrgName", m.get("bizOrgName"));
                mapList.add(map);
            }
        }
        if (mapList.size() > 0) {
            try {
                emqKeeper.getMqttClient().publish("jcs/sign/put", JSONObject.toJSONString(mapList).getBytes(), 1, false);
            } catch (MqttException exp) {
                log.info(String.format("发送eqm转kafka消息失败：%s", exp.getMessage()));
            }
        }
        if (mapList.size() == 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("bizOrgCode", "");
            mapList.add(map);
            try {
                emqKeeper.getMqttClient().publish("jcs/sign/put", JSONObject.toJSONString(mapList).getBytes(), 1, false);
            } catch (MqttException exp) {
                log.info(String.format("发送eqm转kafka消息失败：%s", exp.getMessage()));
            }
        }
    }

    public Map<String, Object> getCenterSignStats(String bizOrgCode, String date, Integer targetPassNum, String stationType) {
        List<Map<String, Object>> queryMaps = baseMapper.selectCenterSignStats(bizOrgCode, date, targetPassNum, stationType);
        int passedStationNum = 0;
        long allStationNum = stationInfoMapper.count(bizOrgCode, stationType);

        for (Map<String, Object> queryMap : queryMaps) {
            String status = queryMap.get("status").toString();
            if (Objects.equals("pass", status)) {
                passedStationNum++;
            }
        }

        final int finalPassedStationNum = passedStationNum;
        final int finalPassedStationNum1 = passedStationNum;
        return new HashMap<String, Object>() {{
            this.put("pass", finalPassedStationNum);
            this.put("fail", allStationNum - finalPassedStationNum1);
        }};
    }

    public Map<String, Object> getStationSignStats(String bizOrgCode) {
        List<Map<String, Object>> maps = baseMapper.selectStationSignStats(bizOrgCode);
        List<String> xAxis = new ArrayList<>();
        List<Long> yAxis = new ArrayList<>();

        LocalDate today = LocalDate.now();
        for (int i = 0; i < 7; i++) {
            String date = today.minusDays(i).toString();
            xAxis.add(date);
            yAxis.add(0L);
        }

        if (!maps.isEmpty()) {
            for (Map<String, Object> map : maps) {
                String date = map.get("date").toString();
                long num = Long.parseLong(map.getOrDefault("num", "0").toString());
                if (xAxis.contains(date)) {
                    int index = xAxis.indexOf(date);
                    yAxis.set(index, num);
                }
            }
        }

        return new HashMap<String, Object>() {{
            this.put("xAxis", xAxis);
            this.put("yAxis", yAxis);
        }};
    }

    public IPage<Map<String, Object>> getStationAttendanceStatsPage(
            IPage<?> page,
            String date,
            String stationType,
            String bizOrgCode,
            String attendanceStatus,
            Integer targetPassNum,
            String sorter
    ) {
        String sortField = "", sortOrder = "";
        if (org.springframework.util.StringUtils.hasText(sorter)) {
            sortField = sorter.split("@")[0];
            sortOrder = sorter.split("@")[1];
        }
        return baseMapper.selectStationAttendanceStatsPage(page, date, stationType, bizOrgCode, attendanceStatus, targetPassNum, sortField, sortOrder);
    }
}

