package com.lcrx.selector.aop.implement;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lcrx.selector.aop.annotation.Key;
import com.lcrx.selector.aop.annotation.Module;
import com.lcrx.selector.aop.definition.*;
import com.lcrx.selector.entity.PO.BusinessLogPO;
import com.lcrx.selector.enums.Action;
import com.lcrx.selector.enums.LogType;
import com.lcrx.selector.repository.BusinessLogRepository;
import com.lcrx.selector.utils.RedisHelper;
import com.lcrx.selector.utils.SnowflakeHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author ###
 */
@Slf4j
@Component
public class BusinessLogger {

    private final Logger bizLogger = LoggerFactory.getLogger("biz");
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final BusinessLogRepository businessLogRepository;
    private final SnowflakeHelper snowflakeHelper;

    @Autowired
    public BusinessLogger(BusinessLogRepository businessLogRepository,
                          SnowflakeHelper snowflakeHelper
    )
    {
        this.businessLogRepository = businessLogRepository;
        this.snowflakeHelper = snowflakeHelper;
    }

    @Deprecated
    public void log(LogType logType, Action action, String operator, Object payload) {

        String module = Optional.ofNullable(payload.getClass().getAnnotation(Module.class))
                .map(Module::value).orElse("");

        BusinessLogData businessLogData = new BusinessLogData()
                .activate()
                .setLogType(logType)
                .setAction(action.getDescription())
                .setOperator(operator)
                .setModule(module)
                .setPayload(payload);

        log(businessLogData);
    }

    public void log(BusinessLogData bizLogData) {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        Map<String, Object> logMap = Maps.newHashMap();

        logMap.put("log_type", bizLogData.getLogType().getDescription());
        logMap.put("action", bizLogData.getAction());
        logMap.put("operator", bizLogData.getOperator());
        logMap.put("api", bizLogData.getRequestMethod() + " " + bizLogData.getUri());
        logMap.put("request_url", bizLogData.getUrl());
        logMap.put("remark", bizLogData.getRemark());
        logMap.put("module", bizLogData.getModule());
        logMap.put("loginUser", bizLogData.getLoginUser());
        logMap.put("timeStamp", df.format(new Date()));
        logMap.put("took",bizLogData.getTook());
        logMap.put("headerContext",bizLogData.getHeaderContext());

        Object payload = bizLogData.getPayload();

        if (payload != null) {
            Lists.newArrayList(payload.getClass().getDeclaredFields())
                    .forEach(field -> {

                        if (Objects.nonNull(field.getAnnotation(Key.class))) {
                            Key key = field.getAnnotation(Key.class);
                            field.setAccessible(true);
                            try {
                                logMap.put("k" + key.index(), field.get(payload));
                            } catch (IllegalAccessException e) {
                                log.error("error in log biz info", e);
                            }
                        }

                        if (StringUtils.isBlank(bizLogData.getOperator()) && Objects.nonNull(field.getAnnotation(Operator.class))) {
                            field.setAccessible(true);
                            try {
                                logMap.put("operator", field.get(payload));
                            } catch (IllegalAccessException e) {
                                log.error("error in log biz info", e);
                            }
                        }
                    });
        }

        try {

            logMap.put("payload", objectMapper.writeValueAsString(payload));
            logMap.put("response", objectMapper.writeValueAsString(bizLogData.getResponse()));

            //bizLogger.info(objectMapper.writeValueAsString(logMap));
            BusinessLogPO businessLogPO = new BusinessLogPO();

            businessLogPO.setId(snowflakeHelper.nextId());
            businessLogPO.setContents(JSON.toJSONString(logMap));

            businessLogRepository.save(businessLogPO);

        } catch (JsonProcessingException e) {
            log.error("error in log biz info {}", e);
        }
    }
}
