package cn.axzo.msg.center.message.service.todo;

import cn.axzo.msg.center.dal.SampleTodos;
import cn.axzo.msg.center.dal.TodoBusinessDao;
import cn.axzo.msg.center.dal.TodoBusinesses;
import cn.axzo.msg.center.dal.TodoDao;
import cn.axzo.msg.center.domain.entity.PendingRecordAdapter;
import cn.axzo.msg.center.domain.entity.Todo;
import cn.axzo.msg.center.domain.entity.TodoBusiness;
import cn.axzo.msg.center.message.domain.dto.MessageTemplateDTO;
import cn.axzo.msg.center.message.domain.dto.PendingMessageDTO;
import cn.axzo.msg.center.message.service.MessageTemplateNewService;
import cn.axzo.msg.center.message.service.impl.PendingMessageNewServiceImpl;
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

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

import static java.util.stream.Collectors.toList;

/**
 * 尽量使用已有的逻辑
 *
 * @author yanglin
 */
@Slf4j
@Component
@RequiredArgsConstructor
class TodoRespBuilder {

    private final TodoBusinessDao todoBusinessDao;
    private final TodoDao todoDao;
    private final MessageTemplateNewService messageTemplateNewService;
    private final PendingMessageNewServiceImpl pendingMessageNewServiceImpl;

    // batch convert to old model to reuse the code and save some time

    PendingMessageResponse convertAdapter2MessageResponse(
            PendingRecordAdapter adapter, TerminalTypeEnum terminalType) {
        List<PendingMessageResponse> responses = convertAdapter2MessageResponse(
                Collections.singletonList(adapter), terminalType);
        return responses.get(0);
    }

    List<PendingMessageResponse> convertAdapter2MessageResponse(
            List<PendingRecordAdapter> adapters, TerminalTypeEnum terminalType) {
        return convertAdapter2MessageDTO(adapters).stream()
                .map(i -> i.toResponse(terminalType))
                .collect(toList());
    }

    List<PendingMessageDTO> convertAdapter2MessageDTO(List<PendingRecordAdapter> adapters) {
        List<String> templateCodes = adapters.stream()
                .map(PendingRecordAdapter::getTemplateCode)
                .filter(Objects::nonNull)
                .distinct()
                .collect(toList());
        // 重新查询模版的收益大于成本
        List<MessageTemplateDTO> messageTemplates = messageTemplateNewService
                .listByTemplateCodes(templateCodes);
        return adapters.stream()
                .map(adapter -> pendingMessageNewServiceImpl.convert(adapter, messageTemplates))
                .collect(toList());
    }

    // convert to old model to reuse the code and save some time

    PendingMessageDTO convertTodoToMessage(Todo todo) {
        TodoBusiness business = todoBusinessDao.getById(todo.getTodoBusinessId());
        return convertTodoToMessage(business, todo);
    }

    PendingMessageDTO convertTodoToMessage(TodoBusiness business, Todo todo) {
        TodoRecordAdapter adapter = TodoRecordAdapter.adaptTodo(business, todo);
        ArrayList<String> templateCodes = new ArrayList<>(2);
        if (business != null)
            templateCodes.add(business.getTemplateCode());
        if (todo != null)
            templateCodes.add(todo.getTemplateCode());
        List<MessageTemplateDTO> messageTemplates = messageTemplateNewService.listByTemplateCodes(templateCodes);
        return pendingMessageNewServiceImpl.convert(adapter, messageTemplates);
    }

    // !! build adapters

    PendingRecordAdapter buildBusinessAdapter(TodoBusiness business) {
        List<PendingRecordAdapter> adapters = buildBusinessAdapters(Collections.singletonList(business));
        return adapters.isEmpty() ? null : adapters.get(0);
    }

    List<PendingRecordAdapter> buildBusinessAdapters(List<TodoBusiness> businesses) {
        if (CollectionUtils.isEmpty(businesses))
            return Collections.emptyList();
        boolean emptyBizCodePresent = businesses.stream()
                .anyMatch(biz -> StringUtils.isBlank(biz.getBizCode()));
        boolean sampleTodoAbsent = businesses.stream()
                .anyMatch(biz -> StringUtils.isBlank(biz.getSampleTodoCode()));
        // 如果业务方没有传bizCode, 就取最近的待办, 防止模版变更
        SampleTodos samples = emptyBizCodePresent || sampleTodoAbsent
                ? todoDao.getLatestExecutableTodos(businesses)
                : todoDao.getSampleTodos(businesses);
        // 因为待办详情需要通过待办的 identityCode 来查询数据
        // 所以这里为了兼容老接口需要查询待办获取 identityCode
        ArrayList<PendingRecordAdapter> adapters = new ArrayList<>();
        for (TodoBusiness business : businesses) {
            Todo todo = samples.findSample(business.getId()).orElse(null);
            if (todo != null)
                adapters.add(TodoRecordAdapter.adaptBusiness(business, todo));
            else
                log.warn("Can't find sample todo for business. are todos deleted? businessId={}", business.getId());
        }
        return adapters;
    }

    List<PendingRecordAdapter> buildTodoAdapters(List<Todo> todos) {
        if (CollectionUtils.isEmpty(todos))
            return Collections.emptyList();
        TodoBusinesses businesses = todoBusinessDao.getBusinesses(todos);
        return todos.stream()
                .map(todo -> {
                    TodoBusiness business = businesses.findBusiness(todo).orElse(null);
                    return TodoRecordAdapter.adaptTodo(business, todo);
                })
                .collect(toList());
    }

}