package jnpf.personnels.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jnpf.ContractSignPersonnelNoticeApi;
import jnpf.model.enums.ExamConfigEnums;
import jnpf.model.enums.FContractSignStatus;
import jnpf.model.enums.StaffWorkerStatus;
import jnpf.model.personnels.dto.contractinfo.ContactStatusInfo;
import jnpf.model.personnels.po.FtbPersonnelsStaffRegistrationFormData;
import cn.hutool.json.JSONUtil;
import jnpf.model.enums.FContractSignStatus;
import jnpf.model.personnels.dto.contractinfo.ContactStatusInfo;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.personnels.service.FtbPersonnelsContactInfoService;
import jnpf.personnels.service.FtbPersonnelsStaffRegistrationFormDataService;
import jnpf.personnels.service.FtbPersonnelsStaffRosterService;
import jnpf.personnels.utils.NoSendContactIMUtils;
import jnpf.personnels.utils.PersonnelOrgUtils;
import jnpf.personnels.utils.PersonnelStaffUtils;
import jnpf.vo.ContractSignPersonnelNoticeConfigVo;
import jnpf.personnels.utils.PersonnelOrgUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
@Slf4j
public class FtbPersonnelsContactInfoServiceImpl implements FtbPersonnelsContactInfoService {


    @Autowired
    private FtbPersonnelsStaffRegistrationFormDataService registrationFormDataService;


    @Autowired
    private PersonnelOrgUtils personnelOrgUtils;

    @Autowired
    private FtbPersonnelsStaffRosterService staffRosterService;

    @Autowired
    private NoSendContactIMUtils noSendContactIMUtils;

    @Autowired
    private ContractSignPersonnelNoticeApi contractSignPersonnelNoticeApi;


    @Override
    @Transactional
    public void syncContactInfo(ContactStatusInfo info) {
        log.error("syncContactInfo data = {}", JSONUtil.toJsonStr(info));
        ContactStatusInfo.ContactFieldInfo contactFieldInfo = info.getContactFieldInfo();
        String userId = info.getUserId();
        FContractSignStatus fContractSignStatus = FContractSignStatus.fromCode(info.getContractStatus());
        if (null == fContractSignStatus) {
            throw new RuntimeException("合同签署状态不正确");
        }
        //查询用户
        FtbPersonnelsStaffRoster entity = staffRosterService.queryRosterInfoByUserId(userId);
        if (null == entity) {
            throw new RuntimeException("用户不存在");
        }
        //修改花名册主表
        LambdaUpdateWrapper<FtbPersonnelsStaffRoster> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(FtbPersonnelsStaffRoster::getContractStatus, info.getContractStatus());

        if (null != contactFieldInfo) {
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractType())) {
                wrapper.set(FtbPersonnelsStaffRoster::getContractType, contactFieldInfo.getContractType());
            } else {
                wrapper.set(FtbPersonnelsStaffRoster::getContractType, "");
            }
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractTypeName())) {
                wrapper.set(FtbPersonnelsStaffRoster::getContractTypeName, contactFieldInfo.getContractTypeName());
            } else {
                wrapper.set(FtbPersonnelsStaffRoster::getContractTypeName, "");
            }
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractEffectiveDate())) {
                wrapper.set(FtbPersonnelsStaffRoster::getContractEffectiveDate, personnelOrgUtils.stringDateToDate(contactFieldInfo.getContractEffectiveDate()));
            } else {
                wrapper.set(FtbPersonnelsStaffRoster::getContractEffectiveDate, null);
            }
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractDate())) {
                wrapper.set(FtbPersonnelsStaffRoster::getContractEndDate, personnelOrgUtils.stringDateToDate(contactFieldInfo.getContractDate()));
            } else {
                wrapper.set(FtbPersonnelsStaffRoster::getContractEndDate, null);
            }

            if (StringUtils.isNotEmpty(contactFieldInfo.getContractCompany())) {
                wrapper.set(FtbPersonnelsStaffRoster::getContractCompany, contactFieldInfo.getContractCompany());
            } else {
                wrapper.set(FtbPersonnelsStaffRoster::getContractCompany, "");
            }
        }

        wrapper.eq(FtbPersonnelsStaffRoster::getUserId, userId);
        wrapper.eq(FtbPersonnelsStaffRoster::getId, entity.getId());
        //人事花名册列表只展示劳务合同
        if(info.getIsPersonal().equals(1)) {
            staffRosterService.update(wrapper);
        }

        //修改花名册附表

        registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractStatus", fContractSignStatus.getCode().toString());

        if (null != contactFieldInfo) {

            if (StringUtils.isNotEmpty(contactFieldInfo.getContractCompany())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractCompany", contactFieldInfo.getContractCompany());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractCompany", "");
            }
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractEffectiveDate())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractEffectiveDate", contactFieldInfo.getContractEffectiveDate());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractEffectiveDate", "");
            }
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractName())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractName", contactFieldInfo.getContractName());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractName", "");
            }
            if (StringUtils.isNotEmpty(contactFieldInfo.getContractNum())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractNum", contactFieldInfo.getContractNum());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractNum", "0");
            }

            if (StringUtils.isNotEmpty(contactFieldInfo.getContractType())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractType", contactFieldInfo.getContractType());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractType", "");
            }

            if (CollectionUtil.isNotEmpty(contactFieldInfo.getContractFile())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractFile", JSONUtil.toJsonStr(contactFieldInfo.getContractFile()));
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractFile", "");
            }

            if (StringUtils.isNotEmpty(contactFieldInfo.getContractDate())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractDate", contactFieldInfo.getContractDate());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractDate", "");
            }

            if (StringUtils.isNotEmpty(contactFieldInfo.getContractDetail())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractDetail", contactFieldInfo.getContractDetail());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractDetail", "");
            }

            if (StringUtils.isNotEmpty(contactFieldInfo.getContractTaskId())) {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractTaskId", contactFieldInfo.getContractTaskId());
            } else {
                registrationFormDataService.updateForOneField(entity.getId(), entity.getPhone(), "contractTaskId", "");
            }


        }

    }

    @Override
    public void checkNotSendContactSign(String tenantId) {
        //todo调用接口查询通知配置
        ContractSignPersonnelNoticeConfigVo config = contractSignPersonnelNoticeApi.config(tenantId);
        log.error("ContractSignPersonnelNoticeConfigVo={}", JSONUtil.toJsonStr(config));
        if (null == config) {
            return;
        }
        //启用状态 0启用 1禁用
        if (config.getEnable().equals(1)) {
            return;
        }
        if (CollectionUtil.isEmpty(config.getNoticePersonList())) {
            return;
        }
        List<String> userIds = new ArrayList<>();
        for (ContractSignPersonnelNoticeConfigVo.NoticePerson noticePerson : config.getNoticePersonList()) {
            userIds.add(noticePerson.getUserId());
        }
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        if (StringUtils.isEmpty(config.getNoticeTime())) {
            return;
        }
        // 解析时间
        String[] split = config.getNoticeTime().split(":");
        int alertHour = Integer.valueOf(split[0]);
        LocalTime now = LocalTime.now();
        int currHour = now.getHour();
        if (currHour != alertHour) {
            return;
        }

        //查询用户信息
        QueryWrapper<FtbPersonnelsStaffRoster> rosterWrapper = new QueryWrapper<>();
        rosterWrapper.lambda()
                .in(FtbPersonnelsStaffRoster::getUserId, userIds)
                .notIn(FtbPersonnelsStaffRoster::getWorkerStatus,StaffWorkerStatus.RESIGNED.getCode(),StaffWorkerStatus.PENDING_RESIGNATION.getCode())
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        List<FtbPersonnelsStaffRoster> rosterList = staffRosterService.list(rosterWrapper);
        if (CollectionUtil.isEmpty(rosterList)) {
            return;
        }

        QueryWrapper<FtbPersonnelsStaffRoster> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(FtbPersonnelsStaffRoster::getEnabledMark, 0)
                .notIn(FtbPersonnelsStaffRoster::getWorkerStatus,StaffWorkerStatus.RESIGNED.getCode(),StaffWorkerStatus.PENDING_RESIGNATION.getCode())
                .eq(FtbPersonnelsStaffRoster::getContractStatus, FContractSignStatus.NOT_INITIATED.getCode());
        List<FtbPersonnelsStaffRoster> msgRosterList = staffRosterService.list(wrapper);
        if (CollectionUtil.isEmpty(msgRosterList)) {
            return;
        }
        Date currDate = new Date();
        List<FtbPersonnelsStaffRoster> sendRosterList = new ArrayList<>();
        Date today = PersonnelStaffUtils.getTodayDate();
        String strToday = DateUtil.format(today, "yyyy-MM-dd");
        for (FtbPersonnelsStaffRoster roster : msgRosterList) {
            Date endDate = roster.getActualStartDate();
            if(endDate==null){
                continue;
            }
            if (currDate.after(endDate)) {
                long betweenDay = DateUtil.betweenDay(endDate, today, false);
                if (config.getNoticeFrequency().equals(1)) {//提醒频率 0:每7天提醒 1:每天提醒
                    sendRosterList.add(roster);
                } else if (config.getNoticeFrequency().equals(0)) {
                    //每7天提醒
                    if (checkContactStatus(endDate, today, strToday)) {
                        sendRosterList.add(roster);
                    }
                }
            }
        }
        if (CollectionUtil.isNotEmpty(sendRosterList)) {
            sendAlertMsg(tenantId, sendRosterList, rosterList);
        }
    }


    public static Boolean checkContactStatus(Date endDate, Date today, String strToday) {
        String strEnd = DateUtil.format(endDate, "yyyy-MM-dd");
        if (strEnd.equals(strToday)) {
            return false;
        }
        int num = 0;
        while (true) {
            if (num <= 0) {
                endDate = DateUtil.offsetDay(endDate, 6);
            } else {
                endDate = DateUtil.offsetDay(endDate, 7);
            }
            if (endDate.after(today)) {
                break;
            }
            strEnd = DateUtil.format(endDate, "yyyy-MM-dd");

            if (strToday.equals(strEnd)) {
                return true;
            }
            num++;
        }
        return false;
    }

    private void sendAlertMsg(String tenantId, List<FtbPersonnelsStaffRoster> msgRosterList, List<FtbPersonnelsStaffRoster> toRosterList) {
        noSendContactIMUtils.sendMsg(tenantId, msgRosterList, toRosterList);
    }


    @Override
    public void FileListZip(String rootDir, String userId, HttpServletResponse response) {
        FtbPersonnelsStaffRoster oldRoster = staffRosterService.queryRosterInfoByUserId(userId);
        if (null == oldRoster) {
            throw new RuntimeException("未查询到员工信息");
        }
        FtbPersonnelsStaffRegistrationFormData formData = registrationFormDataService.queryOneFieldForFieldId(oldRoster.getId(), "contractDetail");
        FtbPersonnelsStaffRegistrationFormData contractFile = registrationFormDataService.queryOneFieldForFieldId(oldRoster.getId(), "contractFile");

        List<ContactStatusInfo.ContactInfoFile> contactList = new ArrayList<>();
        if (StringUtils.isNotEmpty(formData.getValue()) && !"[]".equals(formData.getValue())) {
            contactList = JSONUtil.toList(formData.getValue(), ContactStatusInfo.ContactInfoFile.class);
        }
        if(StringUtils.isNotEmpty(contractFile.getValue()) && !contractFile.getValue().equals("[]")) {
            if (!contractFile.getValue().contains("{")) {
                List<ContactStatusInfo.ContactInfoFile> fileList = convertOldContractFile(contractFile.getValue());
                if(CollectionUtil.isNotEmpty(fileList)){
                    contactList.addAll(fileList);
                }
            }else{
                contactList.addAll(JSONUtil.toList(contractFile.getValue(), ContactStatusInfo.ContactInfoFile.class));
            }
        }
        if(CollectionUtil.isEmpty(contactList)){
            throw new RuntimeException("未查询到员工合同信息");
        }


        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
        for (ContactStatusInfo.ContactInfoFile file : contactList) {
            if(!file.getUrl().startsWith("http")){
                continue;
            }
            URL url = null;
            try {
                url = new URL(file.getUrl());
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    InputStream inputStream = connection.getInputStream();
                    String forname = "";
                    if (StringUtils.isNotEmpty(file.getName())) {
                        forname = file.getName();
                    } else {
                        forname = file.getUrl().substring(file.getUrl().lastIndexOf("/") + 1);
                    }
                    zipOutputStream.putNextEntry(new ZipEntry(forname));
                    byte[] bytes = IoUtil.readBytes(inputStream);
                    IOUtils.write(bytes, zipOutputStream);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }
        try {
            zipOutputStream.flush();
            zipOutputStream.closeEntry();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        String zipName = rootDir + ".zip";
        try {
            //生成zip文件
//            HttpServletResponse response = ServletUtil.getResponse();
            byte[] dateArr = outputStream.toByteArray();
            response.reset();
//            response.addHeader("Access-Control-Allow-Origin", "*");
//            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
//            response.setHeader("Content-Disposition", "attachment; filename=\"" + zipName + "\"");
            response.addHeader("Content-Length", "" + dateArr.length);
//            response.setContentType("application/octet-stream; charset=UTF-8");
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipName, "UTF-8"));
            IOUtils.write(dateArr, response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private List<ContactStatusInfo.ContactInfoFile>  convertOldContractFile(String formValueStr) {
        List<ContactStatusInfo.ContactInfoFile> fileList = new ArrayList<>();
        List<String> list = JSONUtil.toList(formValueStr, String.class);
        if (CollectionUtil.isNotEmpty(list)) {
            for (String urlPath : list) {
                Path path = Paths.get(urlPath);
                String fileName = path.getFileName().toString();
                // 分离扩展名
                int dotIndex = fileName.lastIndexOf('.');
                String extension = dotIndex == -1 ? "" : fileName.substring(dotIndex+1);
                ContactStatusInfo.ContactInfoFile file = new ContactStatusInfo.ContactInfoFile();
                file.setName(fileName);
                file.setUrl(urlPath);
                file.setFileExtension(extension);
                fileList.add(file);
            }
        }
        return fileList;
    }

}
