package com.engine.salary.util;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.engine.core.exception.ECException;
import com.engine.salary.common.SalaryContext;
import com.engine.salary.exception.ExceptionUtil;
import com.engine.salary.exception.SalaryRunTimeException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import weaver.general.BaseBean;
import weaver.hrm.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 请求执行器
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
@Slf4j
public class ResponseResult<T, R> {

    private static final long serialVersionUID = 1L;

    private final User user;

    private final BaseBean baseBean = new BaseBean();

    private final Boolean isLog = "true".equals(baseBean.getPropValue("hrmSalary", "log"));

    public ResponseResult(User user) {
        this.user = user;
        SalaryContext.get().setValue("user", user);
    }

    public ResponseResult(HttpServletRequest request, HttpServletResponse response, User user) {
        this.user = user;
        SalaryContext.get().setValue("user", user);
        SalaryContext.get().setValue("request", request);
        SalaryContext.get().setValue("response", response);
    }


    /**
     * 统一返回方法
     */
    public String run(Function<T, R> f, T t) {
        try {
            if (isLog) {
                log.info("run salary api , param {}", t);
            }
            return Ok(f.apply(t));
        } catch (SalaryRunTimeException e) {
            log.error("salary api run fail , param {}", t, e);
            return Error(e.getMessage());
        } catch (ECException e) {
            log.error("salary api run fail , param {}", t, e);
            Throwable cause = e.getCause();
            String message = "";
            while (cause != null) {
                Throwable causeTmp = cause.getCause();
                if (causeTmp == null) {
                    message = cause.getMessage();
                }
                cause = causeTmp;
            }
            return Error(message);
        } catch (Exception e) {
            log.error("salary api run fail , param {}", t, e);
            return Error("系统异常!");
        }
    }

    /**
     * 统一返回方法（有参无返回）
     */
    public String run(Consumer<T> f, T t) {
        try {
            if (isLog) {
                log.info("run salary api , param {}", t);
            }
            f.accept(t);
            return Ok();
        } catch (SalaryRunTimeException e) {
            log.error("salary api run fail , param {}", t, e);
            return Error(e.getMessage());
        } catch (ECException e) {
            log.error("salary api run fail , param {}", t, e);
            return Error(ExceptionUtil.getRealMessage(e));
        } catch (Exception e) {
            log.error("salary api run fail , param {}", t, e);
            return Error("系统异常!", e);
        }
    }


    /**
     * 统一返回方法（无参有返回）
     */
    public String run(Supplier<R> f) {
        try {
            if (isLog) {
                log.info("run salary api");
            }
            return Ok(f.get());
        } catch (SalaryRunTimeException e) {
            log.error("salary api run fail", e);
            return Error(e.getMessage());
        } catch (ECException e) {
            log.error("salary api run fail", e);
            Throwable cause = e.getCause();
            return Error(cause.getMessage());
        } catch (Exception e) {
            log.error("salary api run fail", e);
            return Error("系统异常!", e);
        }
    }


    private static String getJsonString(Object apidatas) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(apidatas);
    }

    /**
     * 成功返回
     */
    private String Ok() {
        Map<String, Object> apidatas = new HashMap<>();
        apidatas.put("status", true);
        return JSONObject.toJSONString(apidatas, SerializerFeature.DisableCircularReferenceDetect);
    }


    /**
     * 成功返回
     */
    private String Ok(R r) throws JsonProcessingException {
        Map<String, Object> apidatas = new HashMap<>();
        apidatas.put("status", true);
        apidatas.put("data", r);
        String success = getJsonString(apidatas);
        if (isLog) {
            log.info("run salary api success return {}", success);
        }
        return success;
    }


    /**
     * 失败返回
     */
    private static String Error(String message) {
        Map<String, Object> apidatas = new HashMap<>();
        apidatas.put("status", false);
        apidatas.put("errormsg", message);
        return JSONObject.toJSONString(apidatas, SerializerFeature.DisableCircularReferenceDetect);
    }


    /**
     * 系统异常失败返回
     */
    private static String Error(String message, Exception e) {
        Map<String, Object> apidatas = new HashMap<>();
        apidatas.put("status", false);
        apidatas.put("errormsg", message);
        apidatas.put("error", e.getMessage());
        return JSONObject.toJSONString(apidatas, SerializerFeature.DisableCircularReferenceDetect);
    }

}
