package com.infoepoch.pms.dispatchassistant.domain.oa;

import com.infoepoch.pms.dispatchassistant.common.constant.StoreKeys;
import com.infoepoch.pms.dispatchassistant.common.exception.ValidationException;
import com.infoepoch.pms.dispatchassistant.common.utils.DateTool;
import com.infoepoch.pms.dispatchassistant.common.utils.JsonUtils;
import com.infoepoch.pms.dispatchassistant.domain.basic.store.KeyValueStoreService;
import com.infoepoch.pms.dispatchassistant.domain.oa.organization.OrganizationSyncService;
import com.infoepoch.pms.dispatchassistant.domain.oa.organization.sync.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.xml.ws.BindingProvider;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;

@Service
public class OaOrganizationService {

    private final static Logger logger = LoggerFactory.getLogger(OaOrganizationService.class);

    @Autowired
    private KeyValueStoreService keyValueStoreService;
    @Autowired
    private OrganizationSyncService organizationSyncService;

    @Autowired
    private IOaRepository oaRepository;

    /**
     * 定时同步
     *
     * @param startLastUpdateDate 起始时间
     * @param endLastUpdateDate   截至时间
     */
    @Async
    public void scheduleSyncOaOrganization(Date startLastUpdateDate, Date endLastUpdateDate) {
        syncOaOrganization(startLastUpdateDate, endLastUpdateDate, null);
    }

    /**
     * 同步OA组织信息
     *
     * @param startLastUpdateDate 起始时间
     * @param endLastUpdateDate   截至时间
     * @param orgCode             组织编码
     */
    public void syncOaOrganization(Date startLastUpdateDate, Date endLastUpdateDate, String orgCode) {
        if (StringUtils.isBlank(orgCode)) {
            if (startLastUpdateDate == null || endLastUpdateDate == null) {
                throw new ValidationException("组织编码为空时，起始时间和截至时间不能为空");
            }
        }
        URL url = null;
        try {
            url = new URL(keyValueStoreService.queryValueByKey(StoreKeys.OA_ORGANIZATION_SYNC_URL));
        } catch (MalformedURLException e) {
            logger.error("获取OA组织同步地址失败");
        }
        syncOaOrganizationStart(startLastUpdateDate, endLastUpdateDate, orgCode, url);
    }

    /**
     * 同步接口开始
     *
     * @param startLastUpdateDate 起始时间
     * @param endLastUpdateDate   截至时间
     * @param orgCode             组织编码
     * @param url                 同步地址
     */
    private void syncOaOrganizationStart(Date startLastUpdateDate, Date endLastUpdateDate, String orgCode, URL url) {
        // 先查询一次，获取总记录数
        SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response = getSyncOaOrganizationResponse(1, -1, startLastUpdateDate, endLastUpdateDate, orgCode, url);
        if (response == null) {
            throw new ValidationException("获取OA组织同步响应数据失败");
        }
        int totalRecord = getTotalRecord(response);
        int totalPage = getTotalPage(response);
        if (totalRecord > 0) {
            for (int currentPage = 1; currentPage <= totalPage; currentPage++) {
                syncOaOrganizationExecute(currentPage, totalRecord, startLastUpdateDate, endLastUpdateDate, orgCode, url);
            }
        }
    }

    /**
     * 同步接口执行
     *
     * @param currentPage         当前页码
     * @param totalRecord         总记录数
     * @param startLastUpdateDate 起始时间
     * @param endLastUpdateDate   截至时间
     * @param orgCode             组织编码
     * @param url                 同步地址
     */
    private void syncOaOrganizationExecute(int currentPage, int totalRecord, Date startLastUpdateDate, Date endLastUpdateDate, String orgCode, URL url) {
        SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response = getSyncOaOrganizationResponse(currentPage, totalRecord, startLastUpdateDate, endLastUpdateDate, orgCode, url);
        if(response == null) {
            throw new ValidationException("获取OA组织同步响应数据失败");
        }
        List<SBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputItem> itemList = getSyncDataList(response);
        if (CollectionUtils.isNotEmpty(itemList))
            saveOrganizationData(itemList);
    }

    /**
     * 保存组织信息
     *
     * @param itemList 同步数据列表
     */
    public void saveOrganizationData(List<SBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputItem> itemList) {
        if (CollectionUtils.isNotEmpty(itemList)) {
            try {
                oaRepository.batchInsertOrganization(itemList);
            } catch (Exception e) {
                throw new ValidationException("保存oa组织信息异常！", e);
            }
            organizationSyncService.syncFromOa(itemList);
        } else {
            logger.info("oa组织信息为空。");
        }
    }

    /**
     * 获取接口返回对象
     *
     * @param currentPage         当前页码
     * @param totalRecord         总记录数量
     * @param startLastUpdateDate 开始时间
     * @param endLastUpdateDate   结束时间
     * @param orgCode             组织编号
     * @param url                 请求地址
     * @return 接口返回数据对象
     */
    private SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse getSyncOaOrganizationResponse(int currentPage, int totalRecord, Date startLastUpdateDate, Date endLastUpdateDate, String orgCode, URL url) {
        long start = System.currentTimeMillis();
        SBMDMMDMPageInquiryOAStandardOrgInfoSrv_Service service = new SBMDMMDMPageInquiryOAStandardOrgInfoSrv_Service(url);
        SBMDMMDMPageInquiryOAStandardOrgInfoSrv port = service.getSBMDMMDMPageInquiryOAStandardOrgInfoSrvPort();
        BindingProvider bindingProvider = (BindingProvider) port;
        bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url.toString());
        SBMDMMDMPageInquiryOAStandardOrgInfoSrvRequest request = makeRequest(currentPage, totalRecord, startLastUpdateDate, endLastUpdateDate, orgCode);
        logger.info("调用接口获取oa组织信息，请求参数：{}", JsonUtils.objectToJson(request));
        SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response = port.process(request);
        long end = System.currentTimeMillis();
        logger.info("通过接口拉取oa数据耗时{}s", (end - start) / 1000);
        logger.info("调用接口获取oa组织信息，响应数据：{}", JsonUtils.objectToJson(response));
        if ("Y".equals(response.getErrorFlag())) {
            return response;
        } else {
            logger.info("调用接口获取oa组织信息失败，错误信息：{}", response.getErrorMessage());
            return null;
        }
    }

    /**
     * 获取接口返回数据列表
     *
     * @param response 接口返回数据对象
     * @return 接口数据列表
     */
    private List<SBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputItem> getSyncDataList(SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response) {
        if ("Y".equals(response.getErrorFlag())) {
            if (response.getSBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputCollection() != null) {
                SBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputCollection collection = response.getSBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputCollection();
                if (collection != null)
                    return collection.getSBMDMMDMPageInquiryOAStandardOrgInfoSrvOutputItem();
            }
        }
        return null;
    }

    /**
     * 获取总记录数量
     *
     * @param response 接口返回数据对象
     * @return 总记录数
     */
    private int getTotalRecord(SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response) {
        if ("Y".equals(response.getErrorFlag())) {
            return response.getTOTALRECORD().intValue();
        }
        return -1;
    }

    /**
     * 获取总页码
     *
     * @param response 接口返回数据对象
     * @return 总页码
     */
    private int getTotalPage(SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response) {
        if ("Y".equals(response.getErrorFlag())) {
            return response.getTOTALPAGE().intValue();
        }
        return -1;
    }

    /**
     * 获取当前页码
     *
     * @param response 接口返回数据对象
     * @return 当前页码
     */
    private int getCurrentPage(SBMDMMDMPageInquiryOAStandardOrgInfoSrvResponse response) {
        if ("Y".equals(response.getErrorFlag())) {
            return response.getCURRENTPAGE().intValue();
        }
        return -1;
    }

    /**
     * 创建接口请求体对象
     *
     * @param totalRecord         总记录数
     * @param currentPage         当前页码
     * @param startLastUpdateDate 起始最新更新日期
     * @param endLastUpdateDate   结束最新更新日期
     * @param orgCode             组织编号
     * @return 接口请求体对象
     */
    private SBMDMMDMPageInquiryOAStandardOrgInfoSrvRequest makeRequest(int currentPage, int totalRecord, Date startLastUpdateDate, Date endLastUpdateDate, String orgCode) {
        MsgHeader msgheader = new MsgHeader();
        msgheader.setSOURCESYSTEMID("EPMS");
        msgheader.setSOURCESYSTEMNAME("江苏移动工程项目管理系统");
        msgheader.setPROVINCECODE("JS");
        msgheader.setCURRENTPAGE(new BigDecimal(currentPage));
        msgheader.setTOTALRECORD(new BigDecimal(totalRecord));
        msgheader.setPAGESIZE(new BigDecimal(100));
        msgheader.setUSERID("epms");
        msgheader.setUSERNAME("epms");
        msgheader.setSUBMITDATE(DateTool.dateToXmlDate(new Date()));
        msgheader.setENVIRONMENTNAME("ERP");
        SBMDMMDMPageInquiryOAStandardOrgInfoSrvRequest request = new SBMDMMDMPageInquiryOAStandardOrgInfoSrvRequest();
        request.setMsgHeader(msgheader);
        if (startLastUpdateDate != null) {
            request.setSTARTLASTUPDATEDATE(DateTool.dateToXmlDate(startLastUpdateDate));
        }
        if (endLastUpdateDate != null) {
            request.setENDLASTUPDATEDATE(DateTool.dateToXmlDate(endLastUpdateDate));
        }
        if (StringUtils.isNotBlank(orgCode)) {
            request.setORGCODE(orgCode);
        }
        return request;
    }

}
