package com.zm.order.tool.server.service.impl;

import com.google.common.base.Throwables;
import com.zm.order.tool.server.dao.MetadataDao;
import com.zm.order.tool.server.dao.OrderAddrDao;
import com.zm.order.tool.server.dao.OrderDao;
import com.zm.order.tool.server.dao.OrderDiscountDao;
import com.zm.order.tool.server.dao.OrderItemDao;
import com.zm.order.tool.server.dao.OrderOperationDao;
import com.zm.order.tool.server.dao.OrderStatusFlowsDao;
import com.zm.order.tool.server.dto.ChooseDTO;
import com.zm.order.tool.server.dto.MetadataDTO;
import com.zm.order.tool.server.dto.NewOrderDTO;
import com.zm.order.tool.server.dto.OrderDetailDTO;
import com.zm.order.tool.server.dto.OrderOperateDTO;
import com.zm.order.tool.server.dto.OrderStatusFlowsDTO;
import com.zm.order.tool.server.dto.SearchOrderDTO;
import com.zm.order.tool.server.dto.UpdateMetadataDTO;
import com.zm.order.tool.server.helper.NewPageServiceHelper;
import com.zm.order.tool.server.manager.SearchManager;
import com.zm.order.tool.server.model.BaseIndexOrder;
import com.zm.order.tool.server.model.Metadata;
import com.zm.order.tool.server.model.Order;
import com.zm.order.tool.server.model.OrderAddr;
import com.zm.order.tool.server.model.OrderDiscount;
import com.zm.order.tool.server.model.OrderItem;
import com.zm.order.tool.server.model.OrderOperation;
import com.zm.order.tool.server.model.OrderStatusFlows;
import com.zm.order.tool.server.query.ListMetadataQuery;
import com.zm.order.tool.server.query.ListStatusFlowsQuery;
import com.zm.order.tool.server.query.OrderQuery;
import com.zm.order.tool.server.query.SearchOrderQuery;
import com.zm.order.tool.server.service.ExceptionConstants;
import com.zm.order.tool.server.service.NewPageService;
import com.zm.order.tool.server.utils.ConvertUtils;
import com.zm.util.dto.ExceptionInfo;
import com.zm.util.dto.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 陈标
 * @Description
 * @Date 2020/7/20 0020 10:04
 */
@Service
public class NewPageServiceImpl implements NewPageService {

    private static final Logger logger = LoggerFactory.getLogger(NewPageServiceImpl.class);

    @Autowired
    private SearchManager manager;
    @Autowired
    private NewPageServiceHelper helper;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private OrderStatusFlowsDao orderStatusFlowsDao;
    @Autowired
    private OrderOperationDao orderOperationDao;
    @Autowired
    private OrderItemDao orderItemDao;
    @Autowired
    private OrderDiscountDao orderDiscountDao;
    @Autowired
    private OrderAddrDao orderAddrDao;
    @Autowired
    private MetadataDao metadataDao;

    @Override
    public Result<List<NewOrderDTO>> listOrder(SearchOrderQuery query) {
        Result<List<NewOrderDTO>> result = new Result<>();
        List<NewOrderDTO> newOrderDtoS = new ArrayList<>();
        try {
            // 参数校验
            ExceptionInfo exceptionInfo = helper.checklistOrder(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<String> orderNoList = query.getOrderNoList();
            if (CollectionUtils.isEmpty(orderNoList)) {
                result.setStatus(true);
                result.setData(Collections.EMPTY_LIST);
                return result;
            }
            // 搜索订单
            SearchOrderDTO searchOrderDTO = manager.searchOrder(query);
            if (searchOrderDTO.getTotal() > 0) {
                List<BaseIndexOrder> orderList = searchOrderDTO.getOrderList();
                for (BaseIndexOrder baseIndexOrder : orderList) {
                    NewOrderDTO newOrderDTO = helper.buildNewOrderDTO(baseIndexOrder);
                    newOrderDtoS.add(newOrderDTO);
                }
            }
            result.setData(newOrderDtoS);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listOrder] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result completeOrder(SearchOrderQuery query) {
        Result<NewOrderDTO> result = new Result<>();
        // 参数校验
        try {
            ExceptionInfo exceptionInfo = helper.checkCompleteOrder(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            SearchOrderDTO searchOrderDTO = manager.searchOrder(query);
            if (searchOrderDTO.getTotal() > 0) {
                List<BaseIndexOrder> orderList = searchOrderDTO.getOrderList();
                for (BaseIndexOrder baseIndexOrder : orderList) {
                    int i = orderDao.updateCompletedAt(baseIndexOrder.getOrderId(), baseIndexOrder.getUserId());
                    if (Objects.equals(i, 1)) {
                        OrderOperation orderOperation = helper.buildOrderOperation(baseIndexOrder);
                        orderOperationDao.insert(orderOperation);
                    }

                }
            }
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[completeOrder] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;

    }

    @Override
    public Result<List<OrderStatusFlowsDTO>> listOrderStatusFlows(ListStatusFlowsQuery query) {
        Result<List<OrderStatusFlowsDTO>> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkListOrderStatusFlows(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<OrderStatusFlows> orderStatusFlows = orderStatusFlowsDao.selectList(query);
            List<OrderStatusFlowsDTO> orderStatusFlowsDtoS =
                ConvertUtils.convertList(orderStatusFlows, OrderStatusFlowsDTO.class);
            result.setData(orderStatusFlowsDtoS);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listOrderStatusFlows] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<Integer> countStatusFlows(ListStatusFlowsQuery query) {
        Result<Integer> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkCountStatusFlows(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            int count = orderStatusFlowsDao.count(query);
            result.setData(count);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[countStatusFlows] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result createOrderStatusFlows(OrderStatusFlowsDTO orderStatusFlowsDTO) {
        Result result = new Result();
        try {
            ExceptionInfo exceptionInfo = helper.checkCreateOrderStatusFlows(orderStatusFlowsDTO);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<OrderStatusFlows> list = helper.buildOrderStatusFlows(orderStatusFlowsDTO);
            if (CollectionUtils.isEmpty(list)) {
                logger.error("OrderStatusFlows is empty , orderStatusFlowsDTO{}", orderStatusFlowsDTO.toString());
                result.setException(ExceptionConstants.ORDER_STATUS_FLOWS_ANALYZE);
                return result;
            }
            orderStatusFlowsDao.inserts(list);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listOrderStatusFlows] failed, request:{}, cause by:{}",
                orderStatusFlowsDTO.toString(), Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;

    }

    @Override
    public Result<List<OrderOperateDTO>> listOrderOperate(String orderNo) {
        Result<List<OrderOperateDTO>> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkListOrderOperate(orderNo);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<OrderOperation> orderOperations = orderOperationDao.selectByOrderNo(orderNo);
            List<OrderOperateDTO> orderOperateDtoS = ConvertUtils.convertList(orderOperations, OrderOperateDTO.class);
            result.setData(orderOperateDtoS);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listOrderOperate] failed, request:{}, cause by:{}", orderNo,
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<OrderDetailDTO> getOrderDetail(OrderQuery orderQuery) {
        Result<OrderDetailDTO> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkGetOrderDetail(orderQuery);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            Order order = orderDao.selectByOrderNo(orderQuery.getOrderNo(), orderQuery.getUserId());
            if (Objects.isNull(order)) {
                result.setException(ExceptionConstants.ORDER_NOT_EXISTS);
                return result;
            }
            List<OrderItem> orderItemList =
                orderItemDao.selectByOrderNo(orderQuery.getOrderNo(), orderQuery.getUserId());
            List<OrderDiscount> orderDiscountList =
                orderDiscountDao.selectByOrderNo(orderQuery.getOrderNo(), orderQuery.getUserId());
            OrderAddr orderAddr = orderAddrDao.selectByOrderNo(orderQuery.getOrderNo(), orderQuery.getUserId());
            OrderDetailDTO orderDetailDTO = helper.buildOrderDetail(order, orderItemList, orderDiscountList, orderAddr);
            result.setData(orderDetailDTO);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[getOrderDetail] failed, request:{}, cause by:{}", orderQuery.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;

    }

    @Override
    public Result activated(List<Long> idList) {
        Result result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkActivation(idList);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            orderStatusFlowsDao.activated(idList);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[activated] failed, request:{}, cause by:{}", idList.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result delete(List<Long> idList) {
        Result result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkDelete(idList);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<OrderStatusFlows> orderStatusFlows = orderStatusFlowsDao.selectListById(idList);
            List<Long> deleteIdList = orderStatusFlows.stream().filter(orderStatus -> orderStatus.getIsActivated() == 0)
                .map(OrderStatusFlows::getId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(deleteIdList)) {
                orderStatusFlowsDao.deleted(deleteIdList);
            }
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[delete] failed, request:{}, cause by:{}", idList.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result deleteMetadata(List<Long> idList) {
        Result result = new Result<>();
        ExceptionInfo exceptionInfo = helper.checkDeleteMetadata(idList);
        try {
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            metadataDao.delete(idList);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[deleteMetadata] failed, request:{}, cause by:{}", idList.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result createMetadata(MetadataDTO metadataDTO) {
        Result result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkCreateMetadata(metadataDTO);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<Metadata> metadataList = helper.buildMetadataList(metadataDTO);
            for (Metadata metadata : metadataList) {
                Metadata getMetadata =
                    metadataDao.selectOne(metadata.getBizType(), metadata.getProperty(), metadata.getValue());
                if (Objects.nonNull(getMetadata)) {
                    result.setException(ExceptionConstants.METADATA_IS_EXIST);
                    return result;
                }
            }
            for (Metadata metadata : metadataList) {
                Metadata getMetadata = helper.buildMetadataDTO(metadata);
                metadataDao.insert(getMetadata);
            }

            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[createMetadata] failed, request:{}, cause by:{}", metadataDTO.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<List<MetadataDTO>> listMetadata(ListMetadataQuery query) {
        Result<List<MetadataDTO>> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkListMetadata(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            List<Metadata> metadataList = metadataDao.selectList(query);
            List<MetadataDTO> dtoList = ConvertUtils.convertList(metadataList, MetadataDTO.class);
            result.setData(dtoList);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listMetadata] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<Integer> countMetadata(ListMetadataQuery query) {
        Result<Integer> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkCountMetadata(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            int count = metadataDao.count(query);
            result.setData(count);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[countMetadata] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<List<ChooseDTO>> listOrderType(ListMetadataQuery query) {
        Result<List<ChooseDTO>> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkListOrderType(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            query.setProperty("单据类型");
            List<Metadata> metadataList = metadataDao.selectList(query);
            List<ChooseDTO> list = helper.buildChooseDTO(metadataList);
            result.setData(list);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listOrderType] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<List<ChooseDTO>> listStatus(ListMetadataQuery query) {
        Result<List<ChooseDTO>> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkListStatus(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            query.setProperty("状态");
            List<Metadata> metadataList = metadataDao.selectList(query);
            List<ChooseDTO> list = helper.buildChooseDTO(metadataList);
            result.setData(list);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listStatus] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result<List<ChooseDTO>> listOperation(ListMetadataQuery query) {
        Result<List<ChooseDTO>> result = new Result<>();
        try {
            ExceptionInfo exceptionInfo = helper.checkListOperation(query);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            query.setProperty("操作类型");
            List<Metadata> metadataList = metadataDao.selectList(query);
            List<ChooseDTO> list = helper.buildChooseDTO(metadataList);
            result.setData(list);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[listOperation] failed, request:{}, cause by:{}", query.toString(),
                Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }

    @Override
    public Result updateMetadata(UpdateMetadataDTO updateMetadataDTO) {
        Result result = new Result();
        try {
            ExceptionInfo exceptionInfo = helper.checkUpdateMetadata(updateMetadataDTO);
            if (ExceptionConstants.OK != exceptionInfo) {
                result.setException(exceptionInfo);
                return result;
            }
            Metadata metadata = ConvertUtils.convertObject(updateMetadataDTO, Metadata.class);
            metadataDao.update(metadata);
            result.setStatus(true);
        } catch (Throwable throwable) {
            logger.error("NewPageServiceImpl[updateMetadata] failed, request:{}, cause by:{}",
                updateMetadataDTO.toString(), Throwables.getStackTraceAsString(throwable));
            result.setException(ExceptionConstants.SYSTEM_ERROR);
        }
        return result;
    }
}
