package com.qmth.distributed.print.api;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.boot.api.annotation.Aac;
import com.qmth.boot.api.annotation.BOOL;
import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.distributed.print.business.bean.result.CalculateNotifyResult;
import com.qmth.distributed.print.business.entity.GradeBatch;
import com.qmth.distributed.print.business.entity.GradeBatchPaper;
import com.qmth.distributed.print.business.service.GradeBatchPaperService;
import com.qmth.distributed.print.business.service.GradeBatchService;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.GradeAnalyzePaperStatusEnum;
import com.qmth.teachcloud.common.enums.TaskResultEnum;
import com.qmth.teachcloud.common.enums.TaskStatusEnum;
import com.qmth.teachcloud.common.util.*;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

/**
 * <p>
 * 回调接口前端控制器
 * </p>
 *
 * @author wangliang
 * @since 2022-04-26
 */
@Api(tags = "回调接口Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.notify}")
@Validated
public class NotifyApiController {
    private final static Logger log = LoggerFactory.getLogger(NotifyApiController.class);

    @Resource
    DictionaryConfig dictionaryConfig;

    @Resource
    GradeBatchService gradeBatchService;

    @Resource
    GradeBatchPaperService gradeBatchPaperService;

    @ApiOperation(value = "教研分析进度回调")
    @ApiResponses({@ApiResponse(code = 200, message = "教研分析进度回调", response = CalculateNotifyResult.class)})
    @RequestMapping(value = "/analysis/progress", method = RequestMethod.POST)
    @Aac(auth = BOOL.FALSE)
    @Transactional
    public Result analysisProgress(@ApiParam(value = "接收教研分析回调数据", required = true) @RequestBody String result) throws UnsupportedEncodingException {
        try {
            log.info("analysis_progress,result:{}", result);
            String decodeJson = URLDecoder.decode(result, SystemConstant.CHARSET_NAME);
            log.info("analysis_progress decodeJson:{}", decodeJson);

            String callbackPwd = dictionaryConfig.printOpenDomain().getCallbackPwd();
            Optional.ofNullable(callbackPwd).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("配置文件回调密码为空"));

            String sign = ServletUtil.getRequestAuthorization();
            Optional.ofNullable(sign).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("签名为空"));
            log.info("sign:{}", sign);

            String localSign = URLEncoder.encode(Base64Util.encode(ShaUtils.sha1(callbackPwd + decodeJson)), SystemConstant.CHARSET_NAME);
            log.info("localSign:{}", localSign);

            if (!Objects.equals(localSign, sign)) {
                throw ExceptionResultEnum.ERROR.exception("回调签名不匹配");
            }

            CalculateNotifyResult calculateNotifyResult = JSONObject.toJavaObject(JSONObject.parseObject(decodeJson), CalculateNotifyResult.class);
            List<String> courseCodeList = new ArrayList<>();
            courseCodeList.addAll(calculateNotifyResult.getCourseCode().keySet());
            Collections.sort(courseCodeList);

            String source = Base64Util.encode(ShaUtils.sha1(calculateNotifyResult.getExamId() + courseCodeList.toString()));
            log.info("source:{}", source);

            QueryWrapper<GradeBatch> gradeBatchQueryWrapper = new QueryWrapper<>();
            gradeBatchQueryWrapper.lambda().eq(GradeBatch::getThirdExamId, calculateNotifyResult.getExamId())
                    .eq(GradeBatch::getSource, source);
            GradeBatch gradeBatch = gradeBatchService.getOne(gradeBatchQueryWrapper);
            Optional.ofNullable(gradeBatch).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("批次数据为空"));

            if (Objects.isNull(gradeBatch.getNotifyTime()) ||
                    (Objects.nonNull(gradeBatch.getNotifyTime())
                            && gradeBatch.getNotifyTime().longValue() <= calculateNotifyResult.getTime().longValue())) {
                TaskStatusEnum taskStatus = Objects.nonNull(calculateNotifyResult.getStatus()) ? TaskStatusEnum.valueOf(calculateNotifyResult.getStatus()) : null;
                if (taskStatus == TaskStatusEnum.DATA_VALID || taskStatus == TaskStatusEnum.RUNNING) {
                    gradeBatch.setStatus(GradeAnalyzePaperStatusEnum.CALCULATING);
                } else if (taskStatus == TaskStatusEnum.FINISH) {
                    gradeBatch.setStatus(GradeAnalyzePaperStatusEnum.FINISH_CALCULATE);
                }
                if (Objects.nonNull(calculateNotifyResult.getProgress())) {
                    gradeBatch.setProgress(calculateNotifyResult.getProgress());
                }
                gradeBatch.setNotifyTime(System.currentTimeMillis());
                if (Objects.nonNull(calculateNotifyResult.getResult())) {
                    gradeBatch.setResult(TaskResultEnum.valueOf(calculateNotifyResult.getResult()));
                }
                gradeBatchService.updateById(gradeBatch);

                QueryWrapper<GradeBatchPaper> gradeBatchPaperQueryWrapper = new QueryWrapper<>();
                gradeBatchPaperQueryWrapper.lambda().eq(GradeBatchPaper::getBatchId, gradeBatch.getId());

                List<GradeBatchPaper> gradeBatchPaperList = new ArrayList<>();
                calculateNotifyResult.getCourseCode().forEach((k, v) -> {
                    gradeBatchPaperQueryWrapper.lambda().eq(GradeBatchPaper::getGradeCourseCode, k)
                            .eq(GradeBatchPaper::getEnable, true);
                    GradeBatchPaper gradeBatchPaper = gradeBatchPaperService.getOne(gradeBatchPaperQueryWrapper);
                    Optional.ofNullable(gradeBatchPaper).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("批次科目[" + k + "]数据为空"));

                    if (Objects.isNull(gradeBatchPaper.getStatus()) || (Objects.nonNull(gradeBatchPaper.getStatus()) && gradeBatchPaper.getStatus() != v)) {
                        gradeBatchPaper.setStatus(v);
                        gradeBatchPaper.setUpdateTime(System.currentTimeMillis());
                        gradeBatchPaperList.add(gradeBatchPaper);
                    }
                });
                gradeBatchPaperService.updateBatchById(gradeBatchPaperList);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return ResultUtil.ok(System.currentTimeMillis());
    }
}
