package com.jpsoft.shinestar.modules.base.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jpsoft.shinestar.config.OSSConfig;
import com.jpsoft.shinestar.config.TemperatureConfig;
import com.jpsoft.shinestar.config.WxConfig;
import com.jpsoft.shinestar.modules.base.dao.*;
import com.jpsoft.shinestar.modules.base.entity.*;
import com.jpsoft.shinestar.modules.base.service.PersonDeviceLogService;
import com.jpsoft.shinestar.modules.base.service.PersonInfoService;
import com.jpsoft.shinestar.modules.base.service.WarningPusherService;
import com.jpsoft.shinestar.modules.common.dto.Sort;
import com.jpsoft.shinestar.modules.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author 墨鱼_mo
 * @date 2020-3-15 14:12
 */
@Slf4j
@Transactional
@Component(value = "personDeviceLogService")
public class PersonDeviceLogServiceImpl implements PersonDeviceLogService {

    @Autowired
    private OSSConfig ossConfig;

    @Autowired
    private WxConfig wxConfig;

    @Autowired
    private TemperatureConfig temperatureConfig;

    @Autowired
    private WarningPusherService warningPusherService;

    @Autowired
    private PersonInfoService personInfoService;

    @Resource(name = "personDeviceLogDAO")
    private PersonDeviceLogDAO personDeviceLogDAO;

    @Resource(name = "personInfoDAO")
    private PersonInfoDAO personInfoDAO;

    @Resource(name = "companyInfoDAO")
    private CompanyInfoDAO companyInfoDAO;

    @Resource(name = "deviceInfoDAO")
    private DeviceInfoDAO deviceInfoDAO;

    @Value("${wx.notice.temperatureWarningTmplCode}")
    private String temperatureWarningTmplCode;

    @Value("${mobile.temperatureUrl}")
    private String temperatureUrl;

    @Resource(name="canteenDiningRecordDAO")
    private CanteenDiningRecordDAO canteenDiningRecordDAO;

    @Resource(name="canteenDeviceDAO")
    private CanteenDeviceDAO canteenDeviceDAO;

    @Resource(name="canteenInfoDAO")
    private CanteenInfoDAO canteenInfoDAO;

    @Resource(name="addressInfoDAO")
    private AddressInfoDAO addressInfoDAO;

    @Override
    public String insertLog(String deviceNo, PersonInfo personInfo, BigDecimal temperature, String faceImageUrl,Date recordDate,
                          int matchStatus,String matchMsg,int matchFaceId) {
        PersonDeviceLog personDeviceLog = new PersonDeviceLog();
        personDeviceLog.setId(UUID.randomUUID().toString());
        personDeviceLog.setDeviceNo(deviceNo);

        personDeviceLog.setPersonId(personInfo.getId());
        personDeviceLog.setPersonName(personInfo.getName());

        personDeviceLog.setTemperature(temperature);
        personDeviceLog.setRecordTime(recordDate);
        personDeviceLog.setFaceImage(faceImageUrl);
        personDeviceLog.setMatchStatus(matchStatus);
        personDeviceLog.setMatchFaceId(matchFaceId);
        personDeviceLog.setMatchMsg(matchMsg);
        personDeviceLog.setDelFlag(false);
        personDeviceLog.setCreateTime(new Date());

        personDeviceLogDAO.insert(personDeviceLog);

        return personDeviceLog.getId();
    }

    @Override
    public PersonDeviceLog findByPersonAndRecordTime(Long personId, Date recordTime) {
        return personDeviceLogDAO.findByPersonAndRecordTime(personId,recordTime);
    }

    @Override
    public String deviceInsertLog(String deviceNo, BigDecimal temperature, JSONObject faceImageJson, JSONObject libMatInfoListJson, JSONObject matchPersonInfo, Date date, Integer maskFlag, String faceImageUrl) {
        PersonInfo personInfo = LApiUtil.getPersonCode(libMatInfoListJson, matchPersonInfo);

        LApiUtil lApiUtil = new LApiUtil();

        int matchStatus = 0;
        String matchMsg = "";
        int matchFaceId = 0;

        if (StringUtils.isNotBlank(libMatInfoListJson.getStr("MatchStatus"))) {
            matchStatus = libMatInfoListJson.getInt("MatchStatus");
            matchMsg = lApiUtil.getMatchMsg(libMatInfoListJson.getInt("MatchStatus"),maskFlag,temperature,temperatureConfig);
            if(libMatInfoListJson.containsKey("MatchFaceID")){
                matchFaceId = libMatInfoListJson.getInt("MatchFaceID");
            }
        }

        return insertLog(deviceNo,personInfo,temperature,faceImageUrl,date,matchStatus,matchMsg,matchFaceId);
    }

    @Override
    public Page<PersonDeviceLog> pageSearch(Map<String, Object> searchParams, int pageNumber, int pageSize, boolean count, List<Sort> sortList) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageNumber, pageSize, count).doSelectPage(() -> {
            personDeviceLogDAO.search(searchParams, sortList);
        });

        return page;
    }

    @Override
    public List<PersonDeviceLog> pageList(Map<String, Object> searchParams, List<Sort> sortList){
        return personDeviceLogDAO.search(searchParams, sortList);
    }


    @Override
    public Page<PersonDeviceLog> simplePageSearch(Map<String, Object> searchParams, int pageNumber, int pageSize, boolean count, List<Sort> sortList) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageNumber, pageSize, count).doSelectPage(() -> {
            personDeviceLogDAO.simpleSearch(searchParams, sortList);
        });

        return page;
    }

    @Override
    public PersonDeviceLog get(String id) {
        return personDeviceLogDAO.get(id);
    }

    @Override
    public List<PersonDeviceLog> findByPersonAndDate(Long personId, Date startDate, Date endDate) {
        return personDeviceLogDAO.findByPersonAndDate(personId, startDate, endDate);
    }


    @Override
    public List<Long> queryUnAttendanceList(String companyCode, Date startTime, Date endTime,List<String> excludeCompanyList) {
        return personDeviceLogDAO.queryUnAttendanceList(companyCode, startTime, endTime,excludeCompanyList);
    }

    @Override
    public List<Long> queryUnAttendanceListByCompanyId(String companyId, Date startTime, Date endTime) {
        return personDeviceLogDAO.queryUnAttendanceListByCompanyId(companyId, startTime, endTime);
    }

    @Override
    public List<Long> queryAttendanceList(String companyCode, Date startTime, Date endTime,List<String> excludeCompanyList) {
        return personDeviceLogDAO.queryAttendanceList(companyCode, startTime, endTime,excludeCompanyList);
    }

    @Override
    public List<Long> queryAttendanceListByCompanyId(String companyId, Date startTime, Date endTime) {
        return personDeviceLogDAO.queryAttendanceListByCompanyId(companyId, startTime, endTime);
    }

    @Override
    public long countByAttendance(String companyCode, Date beginDate, Date endDate) {
        return personDeviceLogDAO.countByAttendance(companyCode,beginDate,endDate);
    }

    @Override
    public Integer getDayAbnormalNumByDeviceNoList(DateTime dateTime, Date date, List<String> deviceNoList) {
        Integer total = personDeviceLogDAO.getDayAbnormalNumByDeviceNoList(dateTime,date,deviceNoList,temperatureConfig.getMax());
        if (total == null){
            return 0;
        }else{
            return total;
        }


    }

    @Override
    public PersonDeviceLog findLastPersonLog(Long personId, float temperatureMax) {
        return personDeviceLogDAO.findLastPersonLog(personId,temperatureMax);
    }

    @Override
    public Integer getDayCheckedVistorNumByDeviceNoList(Date startTime, Date endTime, List<String> deviceNoList) {
        return personDeviceLogDAO.getDayCheckedVistorNumByDeviceNoList(startTime,endTime,deviceNoList);
    }

    @Override
    public Page<PersonDeviceLog> findLastPersonLogByCompanyList(DateTime beginOfDay, DateTime endOfDay, List<CompanyInfo> list,int pageNum, int pageSize) {

        Page<PersonDeviceLog> page = PageHelper.startPage(pageNum, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findLastPersonLogByCompanyList(beginOfDay,endOfDay,list);
        });

        return page;
    }

    @Override
    public Page<PersonDeviceLog> findVisitorLogByDeviceNoList(DateTime beginOfDay, DateTime endOfDay, List<String> deviceNoList, int pageIndex, int pageSize) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageIndex, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findVisitorLogByDeviceNoList(beginOfDay,endOfDay,deviceNoList,"0",null);
        });

        return page;
    }

    @Override
    public Page<PersonDeviceLog> findVisitorLogByDeviceNoList(DateTime beginOfDay, DateTime endOfDay, List<String> deviceNoList, int pageIndex, int pageSize,String filter,BigDecimal max) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageIndex, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findVisitorLogByDeviceNoList(beginOfDay,endOfDay,deviceNoList,filter,max);
        });

        return page;
    }




    @Override
    public Page<PersonDeviceLog> findAllPersonLogByDeviceNo(DateTime beginOfDay, DateTime endOfDay,String deviceNoList,int pageIndex, int pageSize) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageIndex, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findAllPersonLogByDeviceNo(beginOfDay,endOfDay,deviceNoList);
        });
        return page;
    }

    @Override
    public Page<PersonDeviceLog> findAllPersonLogByCompanyListAndDeviceNoList(DateTime beginOfDay, DateTime endOfDay, List<CompanyInfo> companyList,List<String> deviceNoList,int pageIndex, int pageSize) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageIndex, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findAllPersonLogByCompanyIdAndDeviceNo(beginOfDay,endOfDay,companyList,deviceNoList);
        });
        return page;
    }

    @Override
    public Page<PersonDeviceLog> findLastTeacherLogByCompanyList(Date beginOfDay, Date endOfDay, List<CompanyInfo> list, int pageIndex, int pageSize) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageIndex, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findLastTeacherLogByCompanyList(beginOfDay,endOfDay,list);
        });

        return page;
    }

    @Override
    public Page<PersonDeviceLog> findLastStudentLogByCompanyList(Date beginOfDay, Date endOfDay, List<CompanyInfo> list, int pageIndex, int pageSize) {
        Page<PersonDeviceLog> page = PageHelper.startPage(pageIndex, pageSize).doSelectPage(() -> {
            personDeviceLogDAO.findLastStudentLogByCompanyList(beginOfDay,endOfDay,list);
        });

        return page;
    }

    @Override
    public Integer getDayCheckedPersonTotalByCompanyList(Date startTime, Date endTime, List<CompanyInfo> list, String popedom) {
        Integer total = personDeviceLogDAO.getDayCheckedPersonNumByCompanyList(startTime, endTime, list, popedom);

        if (total!=null){
            return total;
        }
        else{
            return 0;
        }
    }

    @Override
    public List<PersonDeviceLog> findExpiredVisitorRecord(int limit) {
        return personDeviceLogDAO.findExpiredVisitorRecord(limit);
    }

    @Override
    public int delete(String id) {
        return personDeviceLogDAO.delete(id);
    }

    @Override
    public List<PersonDeviceLog> findByPersonAndDateAndScene(Long personId, Date beginTime, Date endTime, String scene) {
        return personDeviceLogDAO.findByPersonAndDateAndScene(personId, beginTime, endTime,scene);
    }


    @Override
    public int importData() throws ParseException {

        List<PersonDeviceLog> list = personDeviceLogDAO.importData();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        int count = 0;

        for (PersonDeviceLog personDeviceLog :list) {

            Long personId = personDeviceLog.getPersonId();
            PersonInfo personInfo = personInfoDAO.get(personId);

            if(personInfo!=null) {
                Date recordTime = personDeviceLog.getRecordTime();

                String category = isAtRecordTime(recordTime);

                if(StringUtils.isNotEmpty(category)){
                    CompanyInfo companyInfo = companyInfoDAO.get(personInfo.getCompanyId());

                    CanteenDiningRecord canteenDiningRecord = new CanteenDiningRecord();
                    canteenDiningRecord.setId(UUID.randomUUID().toString());
                    canteenDiningRecord.setPersonId(personDeviceLog.getPersonId());
                    canteenDiningRecord.setDeviceNo(personDeviceLog.getDeviceNo());
                    canteenDiningRecord.setIsOutsourcer(companyInfo.getIsOutsourcer());
                    canteenDiningRecord.setCategory(category);

                    String deviceNo = personDeviceLog.getDeviceNo();
                    DeviceInfo deviceInfo = deviceInfoDAO.findByDeviceNo(deviceNo);
                    String deviceId = deviceInfo.getId();

                    CanteenDevice canteenDevice = canteenDeviceDAO.findByDeviceId(deviceId);

                    if(canteenDevice!=null){
                        CanteenInfo canteenInfo = canteenInfoDAO.get(canteenDevice.getCanteenId());
                        if(canteenInfo!=null){
                            canteenDiningRecord.setAddress(canteenInfo.getAddress());
                        }
                    }
                    canteenDiningRecord.setDelFlag(false);
                    canteenDiningRecord.setCreateBy(personDeviceLog.getCreateBy());
                    canteenDiningRecord.setCreateTime(personDeviceLog.getCreateTime());

                    String attendanceDate = "";
                    if(recordTime!=null){
                        attendanceDate = sdf.format(recordTime);
                    }
                    canteenDiningRecord.setAttendanceDate(attendanceDate);
                    canteenDiningRecord.setRecordTime(recordTime);

                    count += canteenDiningRecordDAO.insert(canteenDiningRecord);
                }
            }
        }
        return count;
    }


    private String isAtRecordTime(Date recordTime) throws ParseException {
        String category = "";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String recordDateStr = sdf.format(recordTime);

        String recordDateStr1 = recordDateStr+" 11:00:00";
        String recordDateStr2 = recordDateStr+" 14:00:00";

        String recordDateStr3 = recordDateStr+" 16:30:00";
        String recordDateStr4 = recordDateStr+" 18:30:00";

        String recordDateStr5 = recordDateStr+" 02:00:00";
        String recordDateStr6 = recordDateStr+" 03:40:00";


        //中餐时间
        Date recordDate1 = sdf1.parse(recordDateStr1);
        Date recordDate2 = sdf1.parse(recordDateStr2);
        if(recordTime.compareTo(recordDate1)>=0 && recordTime.compareTo(recordDate2)<=0){
            category ="2";
            return category;
        }

        //晚餐时间
        Date recordDate3 = sdf1.parse(recordDateStr3);
        Date recordDate4 = sdf1.parse(recordDateStr4);
        if(recordTime.compareTo(recordDate3)>=0&&recordTime.compareTo(recordDate4)<=0){
            category ="3";
            return category;
        }

        //宵夜时间
        Date recordDate5 = sdf1.parse(recordDateStr5);
        Date recordDate6 = sdf1.parse(recordDateStr6);
        if(recordTime.compareTo(recordDate5)>=0&&recordTime.compareTo(recordDate6)<=0){
            category ="4";
            return category;
        }

        return category;
    }


    @Override
    public int insert(PersonDeviceLog model) {
        // TODO Auto-generated method stub
        return personDeviceLogDAO.insert(model);
    }

    @Override
    public int update(PersonDeviceLog model) {
        // TODO Auto-generated method stub
        return personDeviceLogDAO.update(model);
    }
}
