package com.casic.missiles.service.Impl.business;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.casic.missiles.core.base.service.IBaseExportService;
import com.casic.missiles.core.model.auth.AuthUser;
import com.casic.missiles.core.shiro.ShiroKit;
import com.casic.missiles.dto.ReturnDTO;
import com.casic.missiles.dto.ReturnUtil;
import com.casic.missiles.dto.business.order.OrderCancelRequest;
import com.casic.missiles.dto.business.order.OrderListRequest;
import com.casic.missiles.dto.business.order.OrderListResponse;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.ExportEnum;
import com.casic.missiles.enums.PrefixCodeEnum;
import com.casic.missiles.enums.business.MeasureTypeEnum;
import com.casic.missiles.enums.business.OrderStatusEnum;
import com.casic.missiles.enums.sample.SampleStatusEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.mapper.business.BusinessDealRecordMapper;
import com.casic.missiles.mapper.business.BusinessOrderListResponseMapper;
import com.casic.missiles.mapper.business.BusinessOrderMapper;
import com.casic.missiles.mapper.business.BusinessOrderSampleRelationMapper;
import com.casic.missiles.model.business.BusinessDealRecord;
import com.casic.missiles.model.business.BusinessOrder;
import com.casic.missiles.model.business.BusinessOrderSampleRelation;
import com.casic.missiles.model.customer.CustomerSampleInfo;
import com.casic.missiles.service.business.IBusinessOrderService;
import com.casic.missiles.service.customer.CustomerSampleService;
import com.casic.missiles.utils.DictCodeUtils;
import com.casic.missiles.utils.NumberGeneratorUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务管理-委托书 服务实现类
 * </p>
 *
 * @author cz
 * @since 2023-02-02
 */
@Service
@AllArgsConstructor
public class BusinessOrderServiceImpl extends ServiceImpl<BusinessOrderMapper, BusinessOrder> implements IBusinessOrderService, PrefixCodeEnum, OrderStatusEnum, SampleStatusEnum, MeasureTypeEnum {

    private final BusinessOrderListResponseMapper orderListResponseMapper;
    private final IBaseExportService iBaseExportService;
    private final CustomerSampleService customerSampleService;
    private final BusinessOrderSampleRelationMapper sampleRelationMapper;
    private final BusinessDealRecordMapper dealRecordMapper;

    /**
     * 1、分页查询  2、批量查询所有的委托书、样品关系 => 进行以sampleId为key主键map list 3、查询计算样品数量
     */
    @Override
    public Page<OrderListResponse> orderListPage(Page<OrderListResponse> page, OrderListRequest request) throws Exception {
        QueryWrapper<OrderListResponse> wrapper = listParamWrapperBuilder(request);
        Page<OrderListResponse> resultPage = this.orderListResponseMapper.selectPage(page, wrapper);
        List<BusinessOrderSampleRelation> orderSampleList = sampleRelationMapper.selectList(null);
        Map<Long, List<BusinessOrderSampleRelation>> orderSampleMap = orderSampleList.stream().collect(
                Collectors.groupingBy(BusinessOrderSampleRelation::getOrderId)
        );
        resultPage.getRecords().forEach(
                orderSample -> orderSample.setSampleCount(orderSampleMap.containsKey(orderSample.getId()) ? orderSampleMap.get(orderSample.getId()).size() : 0)
        );
        for (OrderListResponse customerAdviceInfo : resultPage.getRecords()) {
            DictCodeUtils.convertDictCodeToName(customerAdviceInfo);
        }
        return resultPage;
    }

    /**
     * 1、查询委托书详情 2、对样品列表进行查询 3、设置默认在库标志
     */
    @Override
    public BusinessOrder orderDetail(Long id) {
        BusinessOrder businessOrder = this.baseMapper.selectById(id);
        QueryWrapper<BusinessOrderSampleRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", businessOrder.getId());
        List<BusinessOrderSampleRelation> orderSampleList = sampleRelationMapper.selectList(queryWrapper);
        List<CustomerSampleInfo> customerSampleList = new ArrayList<>();
        for (BusinessOrderSampleRelation orderSample : orderSampleList) {
            CustomerSampleInfo customerSampleInfo = customerSampleService.sampleDetail(orderSample.getSampleId());
            if (null != customerSampleInfo) {
                customerSampleInfo.setSampleStatus(orderSample.getSampleStatus());
                customerSampleInfo.setIsExistSample("1");
                customerSampleInfo.setRelationId(orderSample.getId());
                customerSampleList.add(customerSampleInfo);
            }
        }
        businessOrder.setCustomerSampleInfoList(customerSampleList);
        return businessOrder;
    }

    /**
     * 1、删除样品和委托书的明细关系,填充传输的明细样品数据
     * 2、对样品进行是否在库的判断，如果不存在则入库， 入库操作完成，进行委托书样品关系的绑定
     */
    @Override
    public ReturnDTO updateOrder(BusinessOrder businessOrder) throws Exception {
        if (CollectionUtils.isEmpty(businessOrder.getCustomerSampleInfoList())) {
            return ReturnUtil.failed("样品列表不能为空");
        }
        AuthUser authUser = ShiroKit.getUser();
        businessOrder.setUpdateUser(authUser.getId());
        int updateFlag = this.baseMapper.updateById(businessOrder);
        this.deleteSampleById(businessOrder.getId());
        boolean sampleUpdateFlag = true;
        this.doSampleListPopulation(businessOrder);
        for (CustomerSampleInfo sampleInfo : businessOrder.getCustomerSampleInfoList()) {
            sampleInfo.setDeliverer(businessOrder.getDeliverer());
            sampleInfo.setCustomerNo(businessOrder.getCustomerNo());
            sampleInfo.setDelivererTel(businessOrder.getDelivererTel());
            if ("0".equals(sampleInfo.getIsExistSample())) {
                ReturnDTO returnDTO = customerSampleService.addSample(sampleInfo);
                sampleUpdateFlag = sampleUpdateFlag && returnDTO.getCode().equals(200);
            } else {
                ReturnDTO returnDTO = customerSampleService.updateSample(sampleInfo);
                sampleUpdateFlag = sampleUpdateFlag && returnDTO.getCode() == 200;
            }
            sampleUpdateFlag = sampleUpdateFlag && sampleStatusCreator(businessOrder.getId(), businessOrder.getRemark(), sampleInfo.getMeasureContent(), sampleInfo.getId()) > 0;
        }
        if (updateFlag > 0 && sampleUpdateFlag) {
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    /**
     * 1、删除样品和委托书的明细关系,填充传输的明细样品数据
     * 2、对样品进行是否在库的判断，如果不存在则入库， 入库操作完成，进行委托书样品关系的绑定
     */
    @Override
    @Transactional
    public ReturnDTO addOrder(BusinessOrder businessOrder) throws Exception {
        initOrderInfo(businessOrder);
        int addFlag = this.baseMapper.insert(businessOrder);
        boolean sampleAddFlag = true;
        this.deleteSampleById(businessOrder.getId());
        this.doSampleListPopulation(businessOrder);
        for (CustomerSampleInfo sampleInfo : businessOrder.getCustomerSampleInfoList()) {
            sampleInfo.setDeliverer(businessOrder.getDeliverer());
            sampleInfo.setCustomerNo(businessOrder.getCustomerNo());
            sampleInfo.setMeasureType(INSIDE_MEASURE);
            sampleInfo.setDelivererTel(businessOrder.getDelivererTel());
            if ("0".equals(sampleInfo.getIsExistSample())) {
                ReturnDTO returnDTO = customerSampleService.addSample(sampleInfo);
                sampleAddFlag = sampleAddFlag && returnDTO.getCode().equals(200);
            } else {
                ReturnDTO returnDTO = customerSampleService.updateSample(sampleInfo);
                sampleAddFlag = sampleAddFlag && returnDTO.getCode().equals(200);
            }
            sampleAddFlag = sampleAddFlag && sampleStatusCreator(sampleInfo.getOrderId(), sampleInfo.getRemark(), sampleInfo.getMeasureContent(), sampleInfo.getId()) > 0;
        }
        if (addFlag > 0 && sampleAddFlag) {
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    /**
     * 1、判断是否存在ids，进行其他参数属性的初始化
     * 2、查询查询构建
     * 3、查询样品关系，构建委托书样品数量map集合
     * 4、字典值进行状态转化
     */
    @Override
    public void orderExport(OrderListRequest request, HttpServletResponse response) {
        try {
            List<OrderListResponse> orderResponseList;
            if (!CollectionUtils.isEmpty(request.getIds())) {
                orderResponseList = orderListResponseMapper.selectBatchIds(request.getIds());
            } else {
                QueryWrapper<OrderListResponse> wrapper = listParamWrapperBuilder(request);
                orderResponseList = this.orderListResponseMapper.selectList(wrapper);
            }
            //查询样品关系，构建委托书样品数量map集合，
            List<BusinessOrderSampleRelation> orderSampleList = sampleRelationMapper.selectList(null);
            Map<Long, List<BusinessOrderSampleRelation>> orderSampleMap = orderSampleList.stream().collect(
                    Collectors.groupingBy(BusinessOrderSampleRelation::getOrderId)
            );
            orderResponseList.forEach(
                    orderSample -> orderSample.setSampleCount(orderSampleMap.containsKey(orderSample.getId()) ? orderSampleMap.get(orderSample.getId()).size() : 0)
            );
            //字典转换
            for (OrderListResponse orderListResponse : orderResponseList) {
                orderListResponse.setIsUrgent("1".equals(orderListResponse.getIsUrgent()) ? "是" : "否");
                DictCodeUtils.convertDictCodeToName(orderListResponse);
            }
            iBaseExportService.exportExcel(response, OrderListResponse.class, orderResponseList, ExportEnum.ORDER_EXPORT.getSheetName());
        } catch (Exception ex) {
            log.error("委托书导出出现异常，异常信息为{}", ex);
        }
    }


    /**
     * 通过状态对委托书状态进行更新
     */
    @Override
    public ReturnDTO updateStatusById(OrderCancelRequest orderCancelRequest, String status) {
        int updateFlag = doUpdateStatusById(orderCancelRequest.getId(), status);
        String dealType = "";
        if (status.equals(ALREADY_RECEIVED)) {
            dealType = "委托书接收";
            doUpdateSampleStatus(orderCancelRequest.getId(), TO_RECEIVE);
        } else {
            dealType = "委托书退回";
        }
        int addDealRecordFlag = addDealRecord(orderCancelRequest, dealType);
        if (updateFlag > 0 && addDealRecordFlag > 0) {
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    /**
     * 取消记录，修改委托书状态，同时生成委托书操作日志，供用户查询
     */
    @Override
    @Transactional
    public ReturnDTO cancelOrder(OrderCancelRequest orderCancelRequest) {
        int updateFlag = this.doUpdateStatusById(orderCancelRequest.getId(), ALREADY_CANCEL);
        int addDealRecordFlag = addDealRecord(orderCancelRequest, "委托书取消");
        if (updateFlag > 0 && addDealRecordFlag > 0) {
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    /**
     * 操作记录的查询
     */
    @Override
    public List<BusinessDealRecord> optionRecord(Long id) {
        QueryWrapper<BusinessDealRecord> dealRecordQueryWrapper = new QueryWrapper<BusinessDealRecord>()
                .eq("order_id", id)
                .orderByDesc("create_time");
        return dealRecordMapper.selectList(dealRecordQueryWrapper);
    }

    /**
     * 新增操作记录
     */
    private int addDealRecord(OrderCancelRequest orderCancelRequest, String dealType) {
        AuthUser authUser = ShiroKit.getUser();
        BusinessDealRecord businessDealRecord = BusinessDealRecord.builder()
                .createUser(authUser.getId())
                .createUserName(authUser.getName())
                .dealType(dealType)
                .recordContent(reasonConvert(orderCancelRequest.getReason()))
                .orderId(orderCancelRequest.getId())
                .build();
        return dealRecordMapper.insert(businessDealRecord);
    }


    /**
     * 强调正在做状态更新
     */
    private int doUpdateStatusById(Long orderId, String status) {
        BusinessOrder businessOrder = new BusinessOrder();
        businessOrder.setId(orderId);
        businessOrder.setStatus(status);
        AuthUser authUser = ShiroKit.getUser();
        businessOrder.setUpdateUser(authUser.getId());
        return this.baseMapper.updateById(businessOrder);
    }

    /**
     * 原因字典转化为相应的值
     */
    private String reasonConvert(String reasonIds) {
        String reasonStr = "";
        if (StringUtils.isEmpty(reasonIds)) {
            return reasonStr;
        }
        String[] reasonIdList = reasonIds.split(",");
        for (String reasonId : reasonIdList) {
            String reasonContent = dealRecordMapper.getDictContent(reasonId);
            reasonStr = reasonStr + reasonContent + ",";
        }
        return reasonStr.substring(0, reasonStr.length() - 1);
    }

    private void initOrderInfo(BusinessOrder businessOrder) {
        Long maxNo = this.baseMapper.selectMaxCOrderNo();
        String orderNo = NumberGeneratorUtil.getContactNo(ORDER_PREFIX, maxNo);
        AuthUser authUser = ShiroKit.getUser();
        businessOrder.setCreateUser(authUser.getId());
        businessOrder.setUpdateUser(authUser.getId());
        businessOrder.setOrderCode(orderNo);
        businessOrder.setStatus(NOT_RECEIVED);
    }

    /**
     * 委托书列表查询构建方法
     */
    private QueryWrapper<OrderListResponse> listParamWrapperBuilder(OrderListRequest request) {
        QueryWrapper<OrderListResponse> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(request.getCustomerName()), "customer_name", request.getCustomerName());
        queryWrapper.like(StringUtils.isNotBlank(request.getDeliverer()), "deliverer", request.getDeliverer());
        queryWrapper.like(StringUtils.isNotBlank(request.getOrderCode()), "order_code", request.getOrderCode());
        queryWrapper.like(ObjectUtil.isNotEmpty(request.getIsUrgent()) && request.getIsUrgent() != 2, "is_urgent", request.getIsUrgent());
        queryWrapper.like(StringUtils.isNotBlank(request.getCustomerNo()), "customer_no", request.getCustomerNo());
        queryWrapper.like(ObjectUtil.isNotEmpty(request.getStatus()) && request.getStatus() != 0, "status", request.getStatus());
        queryWrapper.eq("is_del", 0);
        queryWrapper.apply(StringUtils.isNotBlank(request.getStartTime()),
                "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getStartTime());
        queryWrapper.apply(StringUtils.isNotBlank(request.getEndTime()),
                "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getEndTime());
        queryWrapper.orderByDesc("create_time");

        return queryWrapper;
    }

    private int deleteSampleById(Long orderId) {
        QueryWrapper<BusinessOrderSampleRelation> sampleStatusRelationWrapper = new QueryWrapper<BusinessOrderSampleRelation>()
                .eq("order_id", orderId);
        return this.sampleRelationMapper.delete(sampleStatusRelationWrapper);
    }

    private int sampleStatusCreator(Long orderId, String remark, String measureContent, Long sampleId) {
        BusinessOrderSampleRelation sampleStatusPopulation = new BusinessOrderSampleRelation();
        sampleStatusPopulation.setOrderId(orderId);
        sampleStatusPopulation.setRemark(remark);
        sampleStatusPopulation.setSampleId(sampleId);
        sampleStatusPopulation.setMeasureContent(measureContent);
        sampleStatusPopulation.setMeasureType(INSIDE_MEASURE);
        return this.sampleRelationMapper.insert(sampleStatusPopulation);
    }

    /**
     * 强调正在做状态更新
     */
    private int doUpdateSampleStatus(Long orderId, String sampleStatus) {
        QueryWrapper<BusinessOrderSampleRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        BusinessOrderSampleRelation orderSample = new BusinessOrderSampleRelation();
        orderSample.setId(orderId);
        orderSample.setSampleStatus(sampleStatus);
        return this.sampleRelationMapper.update(orderSample, queryWrapper);
    }


    private void doSampleListPopulation(BusinessOrder businessOrder) {
        businessOrder.getCustomerSampleInfoList().forEach(
                customerSampleInfo -> {
                    customerSampleInfo.setOrderId(businessOrder.getId());
                    customerSampleInfo.setCustomerName(businessOrder.getCustomerName());
                    customerSampleInfo.setCustomerId(businessOrder.getCustomerId());
                }
        );
    }

}
