package cn.iocoder.foodnexus.module.order.service.customerorderrecord;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.foodnexus.framework.common.util.CommonUtil;
import cn.iocoder.foodnexus.framework.common.util.spring.SpringUtils;
import cn.iocoder.foodnexus.module.erp.api.PurchaseOrderSplitEvent;
import cn.iocoder.foodnexus.module.order.api.CustomerOrderApi;
import cn.iocoder.foodnexus.module.order.api.CustomerOrderRecordApi;
import cn.iocoder.foodnexus.module.order.controller.admin.customerorder.vo.CustomerOrderRecordMapVO;
import cn.iocoder.foodnexus.module.order.dto.CustomerOrderDTO;
import cn.iocoder.foodnexus.module.order.dto.CustomerOrderRecordEvent;
import cn.iocoder.foodnexus.module.order.enums.CustomerOrderStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.foodnexus.module.order.controller.admin.customerorderrecord.vo.*;
import cn.iocoder.foodnexus.module.order.dal.dataobject.customerorderrecord.CustomerOrderRecordDO;
import cn.iocoder.foodnexus.framework.common.pojo.PageResult;
import cn.iocoder.foodnexus.framework.common.pojo.PageParam;
import cn.iocoder.foodnexus.framework.common.util.object.BeanUtils;

import cn.iocoder.foodnexus.module.order.dal.mysql.customerorderrecord.CustomerOrderRecordMapper;

import static cn.iocoder.foodnexus.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.foodnexus.module.order.enums.ErrorCodeConstants.*;

/**
 * 客户订单进度记录 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
@Slf4j
public class CustomerOrderRecordServiceImpl implements CustomerOrderRecordService, CustomerOrderRecordApi {

    @Resource
    private CustomerOrderRecordMapper customerOrderRecordMapper;

    @Autowired
    private CustomerOrderApi customerOrderApi;

    @Override
    public Long createCustomerOrderRecord(CustomerOrderRecordSaveReqVO createReqVO) {
        // 插入
        CustomerOrderRecordDO customerOrderRecord = BeanUtils.toBean(createReqVO, CustomerOrderRecordDO.class);
        customerOrderRecordMapper.insert(customerOrderRecord);

        // 返回
        return customerOrderRecord.getId();
    }

    @Override
    public void updateCustomerOrderRecord(CustomerOrderRecordSaveReqVO updateReqVO) {
        // 校验存在
        validateCustomerOrderRecordExists(updateReqVO.getId());
        // 更新
        CustomerOrderRecordDO updateObj = BeanUtils.toBean(updateReqVO, CustomerOrderRecordDO.class);
        customerOrderRecordMapper.updateById(updateObj);
    }

    @Override
    public void deleteCustomerOrderRecord(Long id) {
        // 校验存在
        validateCustomerOrderRecordExists(id);
        // 删除
        customerOrderRecordMapper.deleteById(id);
    }

    @Override
        public void deleteCustomerOrderRecordListByIds(List<Long> ids) {
        // 删除
        customerOrderRecordMapper.deleteByIds(ids);
        }


    private void validateCustomerOrderRecordExists(Long id) {
        if (customerOrderRecordMapper.selectById(id) == null) {
            throw exception(CUSTOMER_ORDER_RECORD_NOT_EXISTS);
        }
    }

    @Override
    public CustomerOrderRecordDO getCustomerOrderRecord(Long id) {
        return customerOrderRecordMapper.selectById(id);
    }

    @Override
    public PageResult<CustomerOrderRecordDO> getCustomerOrderRecordPage(CustomerOrderRecordPageReqVO pageReqVO) {
        return customerOrderRecordMapper.selectPage(pageReqVO);
    }

    /**
     * 订单进度记录
     *
     * @param customerOrderId
     * @return
     */
    @Override
    public List<CustomerOrderRecordMapVO> queryRecordMap(Long customerOrderId) {
        List<CustomerOrderRecordDO> list = customerOrderRecordMapper.selectList(CustomerOrderRecordDO::getCustomerOrderId, customerOrderId);
        Map<CustomerOrderStatus, List<CustomerOrderRecordDO>> map = CommonUtil.listConvertListMap(list, CustomerOrderRecordDO::getOrderStatus);
        List<CustomerOrderRecordMapVO> result = new ArrayList<>();
        for (Map.Entry<CustomerOrderStatus, List<CustomerOrderRecordDO>> entry : map.entrySet()) {
            CustomerOrderStatus orderStatus = entry.getKey();
            List<CustomerOrderRecordDO> records = entry.getValue();
            result.add(new CustomerOrderRecordMapVO(orderStatus, BeanUtils.toBean(records, CustomerOrderRecordRespVO.class)));
        }
        result.sort(Comparator.comparingInt(vo -> vo.getOrderStatus().getSort()));

        return result;
    }

    @Override
    public List<CustomerOrderRecordRespVO> queryCurrentRecords(Long customerOrderId, CustomerOrderStatus orderStatus) {
        return BeanUtils.toBean(customerOrderRecordMapper.selectList(CustomerOrderRecordDO::getCustomerOrderId, customerOrderId,
                CustomerOrderRecordDO::getOrderStatus, orderStatus), CustomerOrderRecordRespVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recordEvent(CustomerOrderRecordEvent event) {
        SpringUtils.getApplicationContext().publishEvent(event);
    }

    @Async
    @TransactionalEventListener(classes = CustomerOrderRecordEvent.class, phase = TransactionPhase.AFTER_COMMIT)
    public void addRecordEvent(CustomerOrderRecordEvent event) {
        log.info("客户订单记录：{}", event);
        Long orderId = event.getCustomerOrderId();
        CustomerOrderStatus orderStatus = event.getOrderStatus();
        CustomerOrderDTO orderInfo = customerOrderApi.queryById(orderId);

        String message = String.format(orderStatus.getText(), event.getCopyWriter().toArray(new String[0]));

        CustomerOrderRecordSaveReqVO saveReqVO = new CustomerOrderRecordSaveReqVO();
        saveReqVO.setCustomerId(orderInfo.getCustomerId());
        saveReqVO.setCustomerOrderId(orderId);
        saveReqVO.setOrderStatus(orderStatus);
        saveReqVO.setSupplierId(event.getSupplierId());
        saveReqVO.setMessageInfo(message);
        this.createCustomerOrderRecord(saveReqVO);
    }
}