package com.hr.externelSystem;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.hr.dto.AggregateQueryDTO;
import com.hr.dto.ApiLogDto;
import com.hr.param.AggregateRequest;
import com.hr.repository.domain.*;
import com.hr.repository.jpa.IpLogRepository;
import com.hr.repository.jpa.IpOrderRepository;
import com.hr.util.SnowflakeIdWorker;
import com.hr.vo.CallbackResponseVO;
import com.timevale.esign.paas.tech.util.AesUtil;
import com.yy.basedevelop.common.data.BaseReturnDto;
import com.yy.basedevelop.common.util.ruoyi.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

@Component
@Slf4j
public class BizHandlerFactory {

    @Autowired
    private List<BizHandler> handlers;
    @Autowired
    private IpOrderRepository ipOrderRepository;
    @Autowired
    private IpLogRepository ipLogRepository;

    public BizHandler getHandler(String interfaceCode){
        for (BizHandler handler : handlers) {
            if (handler.getType().getServiceCode().equals(interfaceCode)){
                return handler;
            }
        }
        throw new ServiceException("找不到接口服务：" + interfaceCode);
    }

    /**
     * 接口平台分发数据
     * @param req
     * @param dto
     * @return
     */
    public BaseReturnDto<Object> dispatch(AggregateRequest req, AggregateQueryDTO dto) {
        IpInterfacePO ipInterfacePO = dto.getIpInterfacePO();
        log.info("ipInterfacePO:{}",JSON.toJSONString(ipInterfacePO));
        BizHandler handler = getHandler(ipInterfacePO.getInterfaceNo());
        IpOrderPO ipOrderPO = new IpOrderPO();
        IpLogPO ipLogPO = new IpLogPO();
        String data = req.getData();
        try {
            ApiLogDto logDto = new ApiLogDto();
            IpTokenPO ipTokenPO = dto.getIpTokenPO();
            String decrypt = AesUtil.decrypt(data, ipTokenPO.getSecret());
            Class requestClass = handler.getRequestClass();
            Object o = JSON.parseObject(decrypt, requestClass);
            wrapOrder(req, dto, ipOrderPO, ipInterfacePO,ipLogPO);
            ipOrderPO.setStatus("handle");
            ipOrderRepository.save(ipOrderPO);
            ipLogRepository.save(ipLogPO);
            log.info("openApiHandle:{}",handler.getRequestClass());
            Object handle = handler.handle(o, ipInterfacePO,logDto);
            ipLogPO.setSystemResponse(JSON.toJSONString(handle));
            String errorMessage = logDto.getErrorMessage();
            if(StringUtils.isEmpty(errorMessage)){
                ipOrderPO.setStatus("success");
                ipLogPO.setStatus("success");

            }else{
                ipOrderPO.setStatus("fail");
                ipLogPO.setStatus("fail");
            }

            ipOrderPO.setIid(ipInterfacePO.getId());
            ipOrderPO.setUpdateTime(new Date());
            ipOrderPO.setBusinessNo(logDto.getBusinessNo());
            ipLogPO.setUrl(logDto.getUrl());
            ipLogPO.setRequestParam(logDto.getRequestParam());
            ipLogPO.setUpdateTime(new Date());
            ipLogPO.setResponseResult(logDto.getResponseParam());
            ipLogPO.setHttpStatus(logDto.getHttpStatus());
            ipLogPO.setMsg(logDto.getErrorMessage());
            ipOrderRepository.save(ipOrderPO);
            ipLogRepository.save(ipLogPO);
            return BaseReturnDto.success(handle);
        } catch (Exception e) {
            log.error("数据解密失败",JSON.toJSONString(req),e);
        }
        return BaseReturnDto.error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "数据处理失败");
    }

    private void wrapOrder(AggregateRequest req, AggregateQueryDTO dto, IpOrderPO ipOrderPO, IpInterfacePO ipInterfacePO, IpLogPO ipLogPO) {
        IpTokenInterfacePO ipTokenInterfacePO = dto.getIpTokenInterfacePO();

        ipOrderPO.setId(SnowflakeIdWorker.nextId());
        ipOrderPO.setInterfaceName(ipInterfacePO.getInterfaceName());
        ipOrderPO.setAccNo(req.getAccountNo());
        ipOrderPO.setToken(req.getToken());
        ipOrderPO.setRefId(0L);
        ipOrderPO.setIsCallback(ipTokenInterfacePO.getIsCallback());
        ipOrderPO.setCallbackNum(ipTokenInterfacePO.getCallbackNum());
        ipOrderPO.setCallbackUrl(ipTokenInterfacePO.getCallbackUrl());
        ipOrderPO.setAddTime(new Date());
        ipOrderPO.setTid(dto.getIpTokenInterfacePO().getId());
        ipOrderPO.setManufacturer(ipInterfacePO.getManufacturer());


        ipLogPO.setId(SnowflakeIdWorker.nextId());
        ipLogPO.setOid(ipOrderPO.getId());
        ipLogPO.setAddTime(new Date());
        ipLogPO.setExecuteType("request");
        ipLogPO.setStatus("handle");
    }

    private void wrapCallBackOrder(IpOrderPO ipOrder, CallbackResponseVO callback, Date callDateTime, JSONObject json) {
        IpLogPO ipLog = new IpLogPO();
        IpOrderPO ipOrderPO = new IpOrderPO();
        ipOrderPO.setId(SnowflakeIdWorker.nextId());
        ipOrderPO.setInterfaceName(ipOrder.getInterfaceName());
        ipOrderPO.setAccNo(ipOrder.getAccNo());
        ipOrderPO.setIid(ipOrder.getIid());
        ipOrderPO.setTid(ipOrder.getTid());
        ipOrderPO.setRefId(ipOrder.getId());
        ipOrderPO.setCallbackUrl(ipOrder.getCallbackUrl());
        ipOrderPO.setAddTime(callDateTime);
        ipOrderPO.setUpdateTime(new Date());
        ipOrderPO.setManufacturer(ipOrder.getManufacturer());
        ipOrderPO.setStatus(callback.getStatus() ? "success" : "fail");
        ipOrderPO.setCallbackStatus(callback.getStatus() ? "success" : "fail");

        ipLog.setId(SnowflakeIdWorker.nextId());
        ipLog.setOid(ipOrderPO.getId());
        ipLog.setAddTime(callDateTime);
        ipLog.setRequestParam(json.toJSONString());
        ipLog.setExecuteType("callback");
        ipLog.setStatus(callback.getStatus() ? "success" : "fail");
        ipLog.setUpdateTime(new Date());
        ipLog.setResponseResult(callback.getResponseParam());
        ipOrderRepository.save(ipOrderPO);
        ipLogRepository.save(ipLog);
    }

    public Boolean doCallBack(String interfaceNo, String businessNo, JSONObject json) {

        IpOrderPO ipOrderPO = ipOrderRepository.findByBusinessNo(businessNo);
        if(ipOrderPO == null){
            log.error("找不到对应的业务编码");
            return false;
        }
        String callbackStatus = ipOrderPO.getCallbackStatus();
        if("success".equals(callbackStatus)){
            log.info("当前业务回调已处理,已忽略");
            return true;
        }
        Boolean isCallback = ipOrderPO.getIsCallback();
        if(!isCallback){
            log.info("当前业务未设置回调,已忽略");
            return true;
        }
        BizHandler handler = getHandler(interfaceNo);
        Boolean callbackResult = false;
        ipOrderPO.setCallbackStatus("handle");
        for (int i = 0; i < ipOrderPO.getCallbackNum(); i++) {
            Date callDateTime = new Date();
            CallbackResponseVO result = handler.doCallBack(ipOrderPO, json);
            // 记录调用记录
            wrapCallBackOrder(ipOrderPO,result,callDateTime,json);
            if(result.getStatus()){
                callbackResult = true;
                break;
            }

        }
        ipOrderPO.setCallbackStatus(callbackResult ? "success" : "fail");
        return callbackResult;
    }
}