package com.qmth.themis.business.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qmth.themis.business.bean.cloudmark.*;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.entity.SysConfig;
import com.qmth.themis.business.entity.TBOrg;
import com.qmth.themis.business.service.ThemisCacheService;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.signature.SignatureInfo;
import com.qmth.themis.common.signature.SignatureType;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

/**
 * 同步云阅卷接口工具类
 * <p>
 * Date: 2021/10/29.
 */
@Component
public class CloudMarkUtil {
    private final static Logger log = LoggerFactory.getLogger(CloudMarkUtil.class);

    @Resource
    ThemisCacheService themisCacheService;

    /**
     * 获取accessKey和accessSecret
     *
     * @param baseParams
     * @return
     */
    public BaseParams getAccessKeyAndAccessSecret(BaseParams baseParams) {
        if (Objects.isNull(baseParams.getAccessKey()) && Objects.isNull(baseParams.getAccessSecret())) {
            TBOrg tbOrg = themisCacheService.addOrgCache(baseParams.getOrgId());
            Optional.ofNullable(tbOrg).orElseThrow(() -> new BusinessException(ExceptionResultEnum.ORG_NO));
            baseParams.setAccessKey(tbOrg.getAccessKey());
            baseParams.setAccessSecret(tbOrg.getAccessSecret());
        }
        return baseParams;
    }

    /**
     * 考试成绩考生查询接口
     *
     * @param studentScoreParams
     * @return
     * @throws IOException
     */
    public List<Map> callStudentScoreApi(StudentScoreParams studentScoreParams) throws IOException {
        studentScoreParams.vaildParams();
        this.getAccessKeyAndAccessSecret(studentScoreParams);
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(studentScoreParams), Map.class);

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.CLOUD_MARK_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置云阅卷地址"));

        String url = sysConfig.getConfigValue() + SystemConstant.CLOUD_MARK_EXAM_STUDENT_SCORE_API;
        int pageNumber = 1;
        int pageSize = 100;
        List<Map> students = null;
        for (; ; ) {
            params.put("pageNumber", pageNumber);
            params.put("pageSize", pageSize);
            Long timestamp = System.currentTimeMillis();
            String accessToken = SignatureInfo.build(SignatureType.SECRET, SystemConstant.METHOD, SystemConstant.CLOUD_MARK_EXAM_STUDENT_SCORE_API, timestamp, studentScoreParams.getAccessKey(), studentScoreParams.getAccessSecret());
            String result = HttpUtil.post(url, params, accessToken, timestamp);
            result = StringEscapeUtils.unescapeHtml4(result);
            if (Objects.nonNull(result)) {
                if (result.contains("HTTP")) {
                    log.error("callStudentScoreApi result:{}", result);
                    throw new BusinessException("云阅卷拉取学生成绩失败");
                }
                List<Map> tempList = JSONObject.parseArray(JSONObject.toJSON(result).toString(), Map.class);
                if (Objects.nonNull(tempList) && tempList.size() > 0) {
                    if (Objects.isNull(students)) {
                        students = new ArrayList<>();
                    }
                    students.addAll(tempList);
                    pageNumber++;
                } else {
                    break;
                }
            } else {
                break;
            }
        }
        return students;
    }

    /**
     * 推送云阅卷考试
     *
     * @param saveExamParams
     * @return
     * @throws IOException
     */
    public Long callExamSaveApi(SaveExamParams saveExamParams) throws IOException {
        saveExamParams.vaildParams();
        this.getAccessKeyAndAccessSecret(saveExamParams);

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.CLOUD_MARK_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置云阅卷地址"));

        String url = sysConfig.getConfigValue() + SystemConstant.CLOUD_MARK_EXAM_SAVE_API;
        long timestamp = System.currentTimeMillis();
        String accessToken = SignatureInfo.build(SignatureType.SECRET, SystemConstant.METHOD, SystemConstant.CLOUD_MARK_EXAM_SAVE_API, timestamp, saveExamParams.getAccessKey(), saveExamParams.getAccessSecret());
        saveExamParams.resetDefaultData();
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(saveExamParams), Map.class);
        String result = HttpUtil.post(url, params, accessToken, timestamp);
        result = StringEscapeUtils.unescapeHtml4(result);
        if (result.contains("HTTP")) {
            log.error("callExamSaveApi result:{}", result);
            throw new BusinessException("云阅卷推送考试信息失败");
        }
        Map<String, Object> resultMap = (Map<String, Object>) JSON.parse(result);
        return Long.parseLong(String.valueOf(resultMap.get("id")));
    }

    /**
     * 推送云阅卷科目
     *
     * @param saveSubjectParams
     * @return
     * @throws IOException
     */
    public String callSubjectSaveApi(SaveSubjectParams saveSubjectParams) throws IOException {
        saveSubjectParams.vaildParams();
        this.getAccessKeyAndAccessSecret(saveSubjectParams);

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.CLOUD_MARK_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置云阅卷地址"));

        String url = sysConfig.getConfigValue() + SystemConstant.CLOUD_MARK_SUBJECT_SAVE_API;
        long timestamp = System.currentTimeMillis();
        String accessToken = SignatureInfo.build(SignatureType.SECRET, SystemConstant.METHOD, SystemConstant.CLOUD_MARK_SUBJECT_SAVE_API, timestamp, saveSubjectParams.getAccessKey(), saveSubjectParams.getAccessSecret());
        saveSubjectParams.resetDefaultData();
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(saveSubjectParams), Map.class);
        String result = HttpUtil.post(url, params, accessToken, timestamp);
        result = StringEscapeUtils.unescapeHtml4(result);
        if (result.contains("HTTP")) {
            log.error("callSubjectSaveApi result:{}", result);
            throw new BusinessException("云阅卷推送考试科目信息失败");
        }
        Map<String, Object> resultMap = (Map<String, Object>) JSON.parse(result);
        return String.valueOf(resultMap.get("updateTime"));
    }

    /**
     * 推送云阅卷考生
     *
     * @param saveStudentParams
     * @return
     * @throws IOException
     */
    public String callStudentSaveApi(SaveStudentParams saveStudentParams) throws IOException {
        saveStudentParams.vaildParams();
        this.getAccessKeyAndAccessSecret(saveStudentParams);

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.CLOUD_MARK_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置云阅卷地址"));

        String url = sysConfig.getConfigValue() + SystemConstant.CLOUD_MARK_STUDENT_SAVE_API;
        long timestamp = System.currentTimeMillis();
        String accessToken = SignatureInfo.build(SignatureType.SECRET, SystemConstant.METHOD, SystemConstant.CLOUD_MARK_STUDENT_SAVE_API, timestamp, saveStudentParams.getAccessKey(), saveStudentParams.getAccessSecret());
        saveStudentParams.resetDefaultData();
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(saveStudentParams), Map.class);
        String result = HttpUtil.post(url, params, accessToken, timestamp);
        result = StringEscapeUtils.unescapeHtml4(result);
        if (result.contains("HTTP")) {
            log.error("callStudentSaveApi result:{}", result);
            throw new BusinessException("云阅卷推送考生信息失败");
        }
        Map<String, Object> resultMap = (Map<String, Object>) JSON.parse(result);
        return String.valueOf(resultMap.get("updateTime"));
    }

    /**
     * 推送云阅卷文件
     *
     * @param fileUploadParams
     * @return
     * @throws IOException
     */
    public Boolean callFileUploadApi(FileUploadParams fileUploadParams) throws IOException {
        fileUploadParams.vaildParams();
        this.getAccessKeyAndAccessSecret(fileUploadParams);

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.CLOUD_MARK_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置云阅卷地址"));

        String host = sysConfig.getConfigValue();
        String api = SystemConstant.CLOUD_MARK_FILE_TYPE_UPLOAD_API;
        api = api.replaceAll(SystemConstant.FILE_UPLOAD_VARIABLE_URL, fileUploadParams.getType().getCode());
        String url = host + api;
        long timestamp = System.currentTimeMillis();
        String accessToken = SignatureInfo.build(SignatureType.SECRET, SystemConstant.METHOD, api, timestamp, fileUploadParams.getAccessKey(), fileUploadParams.getAccessSecret());
        fileUploadParams.resetDefaultData();
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(fileUploadParams), Map.class);
        params.remove("type");
        String result = HttpUtil.postFile(url, params, accessToken, timestamp);
        result = StringEscapeUtils.unescapeHtml4(result);
        if (result.contains("HTTP")) {
            log.error("callFileUploadApi result:{}", result);
            throw new BusinessException("云阅卷推送文件信息失败");
        }
        Map<String, Object> resultMap = (Map<String, Object>) JSON.parse(result);
        return (Boolean) resultMap.get("success");
    }

    /**
     * 推送云阅卷更新考生客观题分数
     *
     * @param studentObjectiveScoreParams
     * @return
     * @throws IOException
     */
    public String callStudentObjectiveScoreApi(StudentObjectiveScoreParams studentObjectiveScoreParams) throws IOException {
        studentObjectiveScoreParams.vaildParams();
        this.getAccessKeyAndAccessSecret(studentObjectiveScoreParams);

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.CLOUD_MARK_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置云阅卷地址"));

        String url = sysConfig.getConfigValue() + SystemConstant.CLOUD_MARK_STUDENT_OBJECTIVE_SAVE_API;
        long timestamp = System.currentTimeMillis();
        String accessToken = SignatureInfo.build(SignatureType.SECRET, SystemConstant.METHOD, SystemConstant.CLOUD_MARK_STUDENT_OBJECTIVE_SAVE_API, timestamp, studentObjectiveScoreParams.getAccessKey(), studentObjectiveScoreParams.getAccessSecret());
        studentObjectiveScoreParams.resetDefaultData();
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(studentObjectiveScoreParams), Map.class);
        String result = HttpUtil.post(url, params, accessToken, timestamp);
        result = StringEscapeUtils.unescapeHtml4(result);
        if (result.contains("HTTP")) {
            log.error("callStudentObjectiveScoreApi result:{}", result);
            throw new BusinessException("云阅卷更新考生客观题分数失败");
        }
        Map<String, Object> resultMap = (Map<String, Object>) JSON.parse(result);
        return String.valueOf(resultMap.get("updateTime"));
    }
}
