package cn.axzo.msg.center.message.service.card.log;

import cn.axzo.msg.center.dal.CardDao;
import cn.axzo.msg.center.dal.CardLogDao;
import cn.axzo.msg.center.domain.entity.Card;
import cn.axzo.msg.center.domain.entity.CardLog;
import cn.axzo.msg.center.message.service.card.CardProps;
import cn.axzo.msg.center.message.service.card.CardRequestContext;
import com.google.common.base.Throwables;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author yanglin
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class CardLoggers {

    private final CardDao cardDao;
    private final CardLogDao cardLogDao;
    private final CardProps cardProps;

    public CardLogger createLogger(CardRequestContext<?> requestContext) {
        return createLogger(requestContext, Collections.emptyList());
    }

    public CardLogger createLogger(CardRequestContext<?> requestContext, List<Card> initCards) {
        return new CardLogger() {

            private final boolean enableCardLog = cardProps.isEnableCardLog();
            private final List<Card> cards = enableCardLog ? new ArrayList<>(initCards) : Collections.emptyList();

            @Override
            public void reloadAndLogCards(String operationContext, Exception exception) {
                try {
                    reloadAndLogCardsImpl(operationContext, exception);
                } catch (Exception e) {
                    log.warn("reloadAndLogCards failed. operationContext={}", operationContext, e);
                }
            }

            private void reloadAndLogCardsImpl(String operationContext, Exception exception) {
                if (!enableCardLog) return;
                ArrayList<CardLog> logs = new ArrayList<>();
                for (Card card : cardDao.reloadCards(cards)) {
                    CardLog log = new CardLog();
                    logs.add(log);
                    log.setSenderPersonId(card.getSenderPersonId());
                    log.setSenderOuId(card.getSenderOuId());
                    log.setSenderWorkspaceId(card.getSenderWorkspaceId());
                    log.setReceiverPersonId(card.getReceiverPersonId());
                    log.setReceiverOuId(card.getReceiverOuId());
                    log.setReceiverWorkspaceId(card.getReceiverWorkspaceId());
                    log.setReceiverAppType(card.getReceiverAppType());
                    log.setImReceiveAccount(card.getImReceiveAccount());
                    log.setBizState(card.getBizState());
                    log.setCardState(card.getCardState());
                    log.setIdentityCode(card.getIdentityCode());
                    log.setTemplateCode(card.getTemplateCode());
                    log.setBizMessageId(card.getBizMessageId());
                    log.setBizCode(card.getBizCode());
                    log.setSubBizCode(card.getSubBizCode());
                    log.setContext(operationContext);
                    log.setBatchNo(requestContext.getBatchNo());
                    log.setCardContent(card.getCardContent());
                    log.setError(exception == null ? "" : Throwables.getStackTraceAsString(exception));
                    log.addLogContent("isCardDelete", card.getIsDelete());
                    for (Map.Entry<String, Object> entry : requestContext.getLogContents().entrySet())
                        log.addLogContent(entry.getKey(), entry.getValue());
                }
                cardLogDao.saveBatch(logs);
            }

            @Override
            public void addCard(Card card) {
                if (!enableCardLog) return;
                cards.add(card);
            }

        };
    }

}