package com.qmth.teachcloud.common.kit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qmth.boot.tools.signature.SignatureType;
import com.qmth.teachcloud.common.SignatureEntityTest;
import com.qmth.teachcloud.common.bean.tiku.TikuCourseProperty;
import com.qmth.teachcloud.common.bean.tiku.TikuPaperInfo;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicSchool;
import com.qmth.teachcloud.common.entity.SysConfig;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.util.FileUtil;
import com.qmth.teachcloud.common.util.HttpUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

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

/**
 * 题库工具类
 * <p>
 * Date: 2024/02/28.
 */
@Component
public class TikuUtils {
    private static final Logger log = LoggerFactory.getLogger(TikuUtils.class);

    // 所有请求方法默认为"POST"
    private static final String POST_METHOD = "POST";

    @Resource
    private CommonCacheService commonCacheService;

    /**
     * 获取试卷列表
     *
     * @param schoolId   学校ID
     * @param courseCode 课程代码
     * @param paperName  试卷名称
     * @param account    工号
     * @param pageNumber 第几页(从1开始)
     * @param pageSize   每页条数
     */
    public IPage<TikuPaperInfo> pagePaperInfo(Long schoolId, String courseCode, String paperName, String account, int pageNumber, int pageSize) {
        String hostUrl = getHostUrl(schoolId);
        String url = SystemConstant.TIKU_PAPER_LIST_API;
        validUrl(hostUrl, url);
        String postUrl = hostUrl.concat(url);
        long timestamp = System.currentTimeMillis();
        //参数
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("courseCode", validParam(courseCode, null, true, "科目代码"));
            Object validPaperName = validParam(paperName, null, false, "试卷名称");
            if (validPaperName != null) {
                map.put("paperName", validPaperName);
            }
            Object validAccount = validParam(account, null, false, "教师工号");
            if (validAccount != null) {
                map.put("account", validAccount);
            }
            map.put("pageNumber", validParam(pageNumber, 1, false, "分页参数"));
            map.put("pageSize", validParam(pageSize, 10, false, "分页参数"));

            String result = HttpUtil.post(postUrl, map, createSign(schoolId, timestamp, url), timestamp);
            if (StringUtils.isBlank(result)) {
                throw ExceptionResultEnum.ERROR.exception("无法连接到题库，请确认题库服务配置正确，如有疑问，请联系管理员");
            }
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.containsKey("content")) {
                Page<TikuPaperInfo> page = new Page(pageNumber, pageSize);
                page.setRecords(JSON.parseArray(jsonObject.getString("content"), TikuPaperInfo.class));
                page.setTotal(jsonObject.getInteger("totalElements"));
                page.setPages(jsonObject.getLong("totalPages"));
                return page;
            } else {
                if (jsonObject.containsKey("message")) {
                    throw ExceptionResultEnum.ERROR.exception(jsonObject.getString("message"));
                } else {
                    throw ExceptionResultEnum.ERROR.exception("查询试卷列表失败");
                }
            }
        } catch (IOException e) {
            log.error(SystemConstant.LOG_ERROR, e);
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 获取试卷数据包
     *
     * @param schoolId 学校ID
     * @param paperId  题库试卷ID
     */
    public File getTikuPaperData(Long schoolId, Long paperId) {
        String hostUrl = getHostUrl(schoolId);
        String url = SystemConstant.TIKU_PAPER_DATA_API;
        validUrl(hostUrl, url);
        String postUrl = hostUrl.concat(url);
        long timestamp = System.currentTimeMillis();
        File file = null;
        try {
            //参数
            Map<String, Object> map = new HashMap<>();
            map.put("paperId", validParam(paperId, null, true, "试卷ID"));

            File filePath = SystemConstant.getFileTempDirVar(SystemConstant.ZIP_PREFIX);
            file = HttpUtil.postDownload(postUrl, map, createSign(schoolId, timestamp, url), timestamp, filePath.getPath());
            if (file.exists()) {
                return file;
            } else {
                throw ExceptionResultEnum.ERROR.exception("请在题库管理模块，试卷列表里预览试卷，核对试卷内容确认无误后点击确定");
            }
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 获取试卷知识点
     *
     * @param schoolId   学校ID
     * @param courseCode 课程代码
     */
    public List<TikuCourseProperty> listCourseProperty(Long schoolId, String courseCode) {
        String hostUrl = getHostUrl(schoolId);
        String url = SystemConstant.TIKU_PAPER_PROPERTY_API;
        validUrl(hostUrl, url);
        String postUrl = hostUrl.concat(url);
        long timestamp = System.currentTimeMillis();
        //参数
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("courseCode", validParam(courseCode, null, true, "科目代码"));

            String result = HttpUtil.post(postUrl, map, createSign(schoolId, timestamp, url), timestamp);
            if (result.contains("\"code\":500000")) {
                throw ExceptionResultEnum.ERROR.exception("课程知识点获取失败");
            }
            return JSON.parseArray(result, TikuCourseProperty.class);
        } catch (IOException e) {
            log.error(SystemConstant.LOG_ERROR, e);
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 查询题库服务器接口访问地址
     *
     * @param schoolId
     * @return
     */
    private String getHostUrl(Long schoolId) {
        SysConfig sysConfig = commonCacheService.addSysConfigCache(schoolId, SystemConstant.QUESTION_HOST_URL);
        Optional.ofNullable(sysConfig).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未开通题库模块，请联系管理员"));
        BasicSchool basicSchool = commonCacheService.schoolCache(schoolId);
        return SystemConstant.getHost(sysConfig.getConfigValue(), basicSchool.getCode());
    }

    /**
     * 签名
     *
     * @param time 时间戳
     * @param url  请求URL
     */
    private String createSign(Long schoolId, long time, String url) {
        BasicSchool basicSchool = commonCacheService.schoolCache(schoolId);
        if (basicSchool == null) {
            throw ExceptionResultEnum.ERROR.exception("学校不存在");
        }
        if (!basicSchool.getEnable()) {
            throw ExceptionResultEnum.ERROR.exception("学校已禁用");
        }
        return SignatureEntityTest.build(SignatureType.SECRET, POST_METHOD, url, time, basicSchool.getAccessKey(), basicSchool.getAccessSecret());
    }

    /**
     * 校验参数值并返回
     *
     * @param value        参数值
     * @param defaultValue 默认值
     * @param require      是否必填（true：是，false：否）
     * @param name         参数名称
     */
    private Object validParam(Object value, Object defaultValue, boolean require, String name) {
        if (require && (Objects.isNull(value) || StringUtils.isBlank(value.toString())) && (Objects.isNull(defaultValue) || StringUtils.isBlank(defaultValue.toString()))) {
            throw ExceptionResultEnum.ERROR.exception((StringUtils.isBlank(name) ? "" : name) + "值必填");
        }
        return Objects.isNull(value) || StringUtils.isBlank(value.toString()) ? defaultValue : value;
    }

    /**
     * 校验url是否配置
     *
     * @param urls URL数组
     */
    private void validUrl(String... urls) {
        if (StringUtils.isAnyBlank(urls)) {
            throw ExceptionResultEnum.ERROR.exception("未开通题库模块，请联系管理员");
        }
    }
}
