package com.ghy.web.controller.order;

import com.ghy.common.annotation.Log;
import com.ghy.common.constant.UserConstants;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.page.TableDataInfo;
import com.ghy.common.enums.*;
import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.StringUtils;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.customer.domain.Customer;
import com.ghy.customer.domain.CustomerAddress;
import com.ghy.customer.service.CustomerAddressService;
import com.ghy.customer.service.CustomerService;
import com.ghy.goods.domain.Goods;
import com.ghy.goods.domain.GoodsImgs;
import com.ghy.goods.domain.GoodsStandard;
import com.ghy.goods.service.GoodsImgsService;
import com.ghy.goods.service.GoodsService;
import com.ghy.goods.service.GoodsStandardService;
import com.ghy.order.domain.*;
import com.ghy.order.request.OrderProcessRequest;
import com.ghy.order.service.*;
import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.service.*;
import com.ghy.system.domain.SysArea;
import com.ghy.system.service.ISysAreaService;
import com.ghy.system.service.ISysDeptConfigService;
import com.ghy.system.service.IWxMsgService;
import com.ghy.web.pojo.vo.OrderChangePriceRequest;
import com.ghy.web.pojo.vo.OrderListResponse;
import com.ghy.web.pojo.vo.OrderStandard;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.domain.WorkerCertification;
import com.ghy.worker.service.IWorkerCertificationService;
import com.ghy.worker.service.WorkerService;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 详细订单API
 *
 * @author HH 2022/4/25
 */
@Controller
@RequestMapping("/order/detail")
public class OrderDetailController extends BaseController {

    private final String prefix = "order/detail";

    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private OrderMasterService orderMasterService;
    @Resource
    private CustomerService customerService;
    @Resource
    private WorkerService workerService;
    @Resource
    private OrderGoodsService orderGoodsService;
    @Resource
    private CustomerAddressService addressService;
    @Resource
    private ISysAreaService sysAreaService;
    @Resource
    private GoodsService goodsService;
    @Resource
    private GoodsImgsService goodsImgsService;
    @Resource
    private GoodsStandardService goodsStandardService;
    @Resource
    private FinancialDetailService financialDetailService;
    @Resource
    private OrderFineRecordService orderFineRecordService;
    @Resource
    private IAfterServiceRecordService afterServiceRecordService;
    @Resource
    private FinancialChangeRecordService financialChangeRecordService;
    @Resource
    private IWorkerCertificationService workerCertificationService;
    @Resource
    private IOrderAssessLabelService orderAssessLabelService;
    @Resource
    private FinancialMasterService financialMasterService;
    @Resource
    private ISysDeptConfigService sysDeptConfigService;
    @Resource
    private OrderBehaviorService orderBehaviorService;
    @Resource
    private IWxMsgService wxMsgService;
    @Resource
    private AdapayService adapayService;

    @RequiresPermissions("order:detail:view")
    @GetMapping()
    public String orderDetail() {
        return prefix;
    }

    //    @RequiresPermissions("order:detail:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(OrderDetail orderDetail) {
        startPage();
        if(this.getSysUser().getDept().getParentId() != 101){
            orderDetail.setDeptId(this.getSysUser().getDept().getParentId());
        }
        List<OrderDetail> orderDetails = orderDetailService.selectOrderDetailList(orderDetail);

        Set<Long> customerIds = orderDetails.stream().map(OrderDetail::getCustomerId).collect(Collectors.toSet());
        Map<Long, Customer> customerMap = customerService.selectByIds(customerIds)
                .stream().collect(Collectors.toMap(Customer::getCustomerId, x -> x, (x, y) -> y));

        Set<Long> orderMasterIds = orderDetails.stream().map(OrderDetail::getOrderMasterId).collect(Collectors.toSet());
        List<OrderMaster> orderMasters = orderMasterService.selectByIds(orderMasterIds);
        Map<Long, OrderMaster> orderMasterMap = orderMasters.stream().collect(Collectors.toMap(OrderMaster::getId, x -> x, (x, y) -> y));

        List<FinancialMaster> financialMasters = financialMasterService.selectByOrderMasterIds(orderMasterIds);
        Map<Long, FinancialMaster> financialMasterMap = financialMasters
                .stream().collect(Collectors.toMap(FinancialMaster::getOrderMasterId, x -> x, (x, y) -> y));

        Set<Long> orderDetailIds = orderDetails.stream().map(OrderDetail::getId).collect(Collectors.toSet());
        Map<Long, FinancialDetail> financialDetailMap = financialDetailService.selectByOrderDetailIds(orderDetailIds)
                .stream().collect(Collectors.toMap(FinancialDetail::getOrderDetailId, x -> x, (x, y) -> y));

        Map<Long, FinancialChangeRecord> fcMap = financialChangeRecordService.selectByOrderDetailIds(orderDetailIds)
                .stream().collect(Collectors.toMap(FinancialChangeRecord::getOrderDetailId, x -> x, (x, y) -> y));


        Set<Long> goodsIds = orderMasters.stream().map(OrderMaster::getGoodsId).collect(Collectors.toSet());
        List<Goods> goods = goodsService.selectByIds(goodsIds);
        Map<Long, Goods> goodsMap = goods.stream().collect(Collectors.toMap(Goods::getGoodsId, x -> x, (x, y) -> y));

        Set<Long> workerIds = orderDetails.stream().map(OrderDetail::getWorkerId).collect(Collectors.toSet());
        workerIds.addAll(goods.stream().map(Goods::getWorkerId).collect(Collectors.toSet()));
        Map<Long, Worker> workerMap = workerService.selectByIds(workerIds)
                .stream().collect(Collectors.toMap(Worker::getWorkerId, x -> x, (x, y) -> y));

        for (OrderDetail detail : orderDetails) {
            Customer customer = customerMap.get(detail.getCustomerId());
            detail.setWorker(workerMap.get(detail.getWorkerId()));
            if (customer != null) {
                detail.setCustomerName(customer.getName());
                detail.setCustomerPhone(customer.getPhone());
            }
            OrderMaster orderMaster = orderMasterMap.get(detail.getOrderMasterId());
            if (orderMaster != null) {
                detail.setPayStatus(orderMaster.getPayStatus());
                detail.setPayType(orderMaster.getPayType());
                detail.setPayTime(orderMaster.getPayTime());
                FinancialMaster fm = financialMasterMap.get(detail.getOrderMasterId());
                if (fm != null) {
                    detail.setFinancialMasterMoney(fm.getPayMoney());
                }
                Goods good = goodsMap.get(orderMaster.getGoodsId());
                if (good != null) {
                    detail.setGoods(good);
                    detail.setGoodsWorker(workerMap.get(good.getWorkerId()));
                }
                // 地址信息
                CustomerAddress customerAddress = addressService.selectByCustomerAddressId(orderMaster.getAddressId());
                if(customerAddress != null){
                    detail.setAddressName(customerAddress.getName());
                    detail.setAddressPhone(customerAddress.getPhone());
                    detail.setAddress(customerAddress.getAddress());
                }
            }
            FinancialDetail fd = financialDetailMap.get(detail.getId());
            if (fd != null) {
                detail.setFinancialDetailMoney(fd.getPayMoney());
            }
            FinancialChangeRecord fc = fcMap.get(detail.getId());
            if (fc != null) {
                detail.setChangeMoney(fc.getChangeMoney());
            }
        }

        return getDataTable(orderDetails);
    }

    /**
     * 查询每种订单状态有多少数量
     */
    @GetMapping("/status/count")
    @ResponseBody
    public AjaxResult statusCount() {
        List<OrderStatusCount> statusCount = orderDetailService.statusCount();
        return AjaxResult.success(statusCount);
    }

    @PostMapping("/app/detail")
    @ResponseBody
    public AjaxResult appDetail(@RequestBody OrderDetail request) {
        try {
            // 子单信息
            OrderDetail detail = orderDetailService.selectById(request.getId());
            // 主单信息
            OrderMaster orderMaster = orderMasterService.selectById(detail.getOrderMasterId());
            FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMaster.getId());
            // 初始化属性
            OrderListResponse orderListResponse = new OrderListResponse();
            List<OrderStandard> standardList = new ArrayList<>();

            // 师傅信息
            Worker worker = workerService.selectById(detail.getWorkerId());
            WorkerCertification workerRealInfo = null;
            String workerName = "";
            String masterWorkerName = "";
            String masterCompanyName = "";
            if (worker != null) {
                // 师傅实名信息
                workerRealInfo = workerCertificationService.selectByWorkerId(orderMaster.getWorkerId());
                workerName = workerRealInfo == null ? worker.getName() : workerRealInfo.getName();
            }
            workerRealInfo = null;
            // 大师傅信息
            Worker masterWorker = workerService.selectById(orderMaster.getWorkerId());
            if (masterWorker != null) {
                // 大师傅实名信息
                workerRealInfo = workerCertificationService.selectByWorkerId(orderMaster.getWorkerId());
                masterWorkerName = workerRealInfo == null ? masterWorker.getName() : workerRealInfo.getName();
                masterCompanyName = workerRealInfo == null ? null : workerRealInfo.getCompanyName();
            }

            // 消费者信息
//            Customer customer = customerService.selectByCustomerId(detail.getCustomerId());

            // 商品规格及信息
            List<OrderGoods> orderStandardList = orderGoodsService.selectByOrderDetailId(detail.getId());

            // 商品信息
            GoodsStandard goodsStandard = goodsStandardService.selectById(orderStandardList.get(0).getGoodsStandardId());

            Goods goods = goodsService.selectById(goodsStandard.getGoodsId());

            // 财务信息
            FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(detail.getId());
            BigDecimal detailPayMoney = financialDetail.getPayMoney();
            // 查询子单加价记录
//            FinancialChangeRecord changeRecordQry = new FinancialChangeRecord();
//            changeRecordQry.setOrderDetailId(detail.getId());
//            List<FinancialChangeRecord> financialChangeRecords = financialChangeRecordService.selectFinancialChangeRecordList(changeRecordQry);
//            if (CollectionUtils.isNotEmpty(financialChangeRecords)) {
//                detailPayMoney = detailPayMoney.add(financialChangeRecords.get(0).getChangeMoney());
//            }

            // 地址信息
            CustomerAddress customerAddress = addressService.selectByCustomerAddressId(orderMaster.getAddressId());
            SysArea sysArea = sysAreaService.selectById(customerAddress.getCountryId());
            String completeAddress = sysArea.getMergerName().replaceAll(",", "") + customerAddress.getAddress();

            // 完工图片
            List<String> finishImgList = null;
            if (detail.getOrderStatus() > 3) {
                GoodsImgs qryImgsObj = new GoodsImgs();
                qryImgsObj.setRemark(request.getId().toString());
                qryImgsObj.setImgType(ImgType.FINISH_IMG.getId());
                qryImgsObj.setGoodsId(0L);
                List<GoodsImgs> goodsImgs = goodsImgsService.qryGoodsImgs(qryImgsObj);
                finishImgList = goodsImgs.stream().map(GoodsImgs::getImgUrl).collect(Collectors.toList());
            }

            for (OrderGoods orderGoods : orderStandardList) {
                OrderStandard orderStandard = new OrderStandard();
                orderStandard.setStandardName(orderGoods.getGoodsName());
                orderStandard.setStandardNum(orderGoods.getGoodsNum());
                orderStandard.setServerNum(orderGoods.getServerGoodsNum() == null ? 0 : orderGoods.getServerGoodsNum());
                orderStandard.setWaitServerNum(orderStandard.getStandardNum() - orderStandard.getServerNum());
                standardList.add(orderStandard);
            }
            if (this.checkIsOnlyServer(orderMaster.getId(), detail.getWorkerId())) {
                BigDecimal workerFee = financialMaster.getPayMoney();
                List<FinancialDetail> financialDetailList = financialDetailService.selectByFinancialMasterId(financialMaster.getId());
                for (FinancialDetail param : financialDetailList) {
                    if (!detail.getWorkerId().equals(param.getPayeeId())) {
                        workerFee = workerFee.subtract(param.getPayMoney());
                    }
                }
                orderListResponse.setPayMoney(workerFee);
                orderListResponse.setIsOnlyServ(Boolean.TRUE);
            } else {
                orderListResponse.setPayMoney(detailPayMoney);
                orderListResponse.setIsOnlyServ(Boolean.FALSE);
            }

            // 售后记录
            AfterServiceRecord afterServiceRecord = new AfterServiceRecord();
            afterServiceRecord.setOrderDetailId(detail.getId());
            List<AfterServiceRecord> afterServiceRecordList = afterServiceRecordService.selectAfterServiceRecordList(afterServiceRecord);

            // 查询加价记录
            FinancialChangeRecord changeRecordQry = new FinancialChangeRecord();
            changeRecordQry.setOrderDetailId(detail.getId());
            List<FinancialChangeRecord> financialChangeRecords = financialChangeRecordService.selectFinancialChangeRecordList(changeRecordQry);

            // 编辑返回属性
            orderListResponse.setOrderDetailId(detail.getId());
            orderListResponse.setOrderDetailCode(detail.getCode());
            orderListResponse.setOrderMasterId(detail.getOrderMasterId());
            orderListResponse.setOrderMasterCode(detail.getOrderMasterCode());
            orderListResponse.setGoodsName(goods.getGoodsName());
            orderListResponse.setGoodsLogoUrl(goods.getGoodsImgUrl());
            orderListResponse.setDiscountMoney(financialDetail.getDiscountMoney());
            orderListResponse.setTotalMoney(financialDetail.getTotalMoney());
            orderListResponse.setWorkerName(workerName);
            orderListResponse.setWorkerPhone(worker == null ? "" : worker.getPhone());
            orderListResponse.setMasterWorkerName(masterWorkerName);
            orderListResponse.setMasterCompanyName(masterCompanyName);
            orderListResponse.setMasterWorkerPhone(masterWorker == null ? "" : masterWorker.getPhone());
            orderListResponse.setCustomerName(customerAddress.getName());
            orderListResponse.setCustomerPhone(customerAddress.getPhone());
            orderListResponse.setOrderStatus(detail.getOrderStatus());
            orderListResponse.setPayStatus(orderMaster.getPayStatus());
            orderListResponse.setPayType(orderMaster.getPayType());
            orderListResponse.setStandardList(standardList);
            orderListResponse.setAddress(completeAddress);
            orderListResponse.setServerTime(detail.getRevTime());
            orderListResponse.setExpectTimeStart(detail.getExpectTimeStart());
            orderListResponse.setExpectTimeEnd(detail.getExpectTimeEnd());
            orderListResponse.setExpectTimeStartFront(detail.getExpectTimeStart());
            orderListResponse.setExpectTimeEndFront(detail.getExpectTimeEnd());
            orderListResponse.setCreateTime(detail.getCreateTime());
            orderListResponse.setWorkBeginTime(detail.getWorkBeginTime());
            orderListResponse.setWorkFinishTime(detail.getWorkFinishTime());
            orderListResponse.setRemark(goods.getRemark());
            orderListResponse.setCustomerRemark(orderMaster.getRemark());
            orderListResponse.setFinishImgList(finishImgList);
            orderListResponse.setWorkerRemark(detail.getRemark());
            orderListResponse.setAfterServiceRecordList(afterServiceRecordList);
            orderListResponse.setTimeout(detail.getTimeout());
            orderListResponse.setTimeoutFineTimes(detail.getTimeoutFineTimes());
            // TODO: 超时扣费
            orderListResponse.setFinancialChangeRecords(financialChangeRecords);

            return AjaxResult.success(orderListResponse);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error();
        }
    }

    @PostMapping("/app/list")
    @ResponseBody
    public TableDataInfo appList(@RequestBody OrderDetail orderDetail) {

        startPage();
        List<OrderListResponse> orderListResponses = new ArrayList<>();
        List<OrderDetail> list = orderDetailService.selectOrderDetailList(orderDetail);
        list.forEach(detail -> {

            // 主单信息
            OrderMaster orderMaster = orderMasterService.selectById(detail.getOrderMasterId());
            FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMaster.getId());
            // 初始化属性
            OrderListResponse orderListResponse = new OrderListResponse();
            List<OrderStandard> standardList = new ArrayList<>();

            // 师傅信息
            Worker worker = workerService.selectById(detail.getWorkerId());
            WorkerCertification workerRealInfo = null;
            String workerName = "";
            if (worker != null) {
                // 师傅实名信息
                workerRealInfo = workerCertificationService.selectByWorkerId(orderMaster.getWorkerId());
                workerName = workerRealInfo == null ? worker.getName() : workerRealInfo.getName();
            }

            // 消费者信息
//            Customer customer = customerService.selectByCustomerId(detail.getCustomerId());

            // 商品规格及信息
            List<OrderGoods> orderStandardList = orderGoodsService.selectByOrderDetailId(detail.getId());

            // 商品信息
            GoodsStandard goodsStandard = goodsStandardService.selectById(orderStandardList.get(0).getGoodsStandardId());

            Goods goods = goodsService.selectById(goodsStandard.getGoodsId());

            // 财务信息
            FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(detail.getId());
            BigDecimal detailPayMoney = financialDetail.getPayMoney();

            // 查询子单加价记录
            FinancialChangeRecord financialChangeRecord = financialChangeRecordService.selectNotPayRecordByDetailId(detail.getId());
            BigDecimal changeMoney = financialChangeRecord == null ? BigDecimal.ZERO : financialChangeRecord.getChangeMoney();

            // 地址信息
            CustomerAddress customerAddress = addressService.selectByCustomerAddressId(orderMaster.getAddressId());
            SysArea sysArea = sysAreaService.selectById(customerAddress.getCountryId());
            String completeAddress = sysArea.getMergerName().replaceAll(",", "") + customerAddress.getAddress();

            for (OrderGoods orderGoods : orderStandardList) {
                OrderStandard orderStandard = new OrderStandard();
                orderStandard.setStandardName(orderGoods.getGoodsName());
                orderStandard.setStandardNum(orderGoods.getGoodsNum());
                orderStandard.setServerNum(orderGoods.getServerGoodsNum());
                orderStandard.setFinishTime(orderGoods.getFinishTime());
                orderStandard.setWaitServerNum(orderGoods.getGoodsNum() - orderGoods.getServerGoodsNum());
                standardList.add(orderStandard);
            }

            if (this.checkIsOnlyServer(orderMaster.getId(), detail.getWorkerId())) {
                BigDecimal workerFee = financialMaster.getPayMoney();
                List<FinancialDetail> financialDetailList = financialDetailService.selectByFinancialMasterId(financialMaster.getId());
                for (FinancialDetail param : financialDetailList) {
                    if (!detail.getWorkerId().equals(param.getPayeeId())) {
                        workerFee = workerFee.subtract(param.getPayMoney());
                    }
                }
                orderListResponse.setPayMoney(workerFee);
                orderListResponse.setIsOnlyServ(Boolean.TRUE);
            } else {
                orderListResponse.setPayMoney(detailPayMoney);
                orderListResponse.setIsOnlyServ(Boolean.FALSE);
            }

            // 售后记录
//            AfterServiceRecord afterServiceRecord = new AfterServiceRecord();
//            afterServiceRecord.setOrderDetailId(detail.getId());
//            List<AfterServiceRecord> afterServiceRecordList  =afterServiceRecordService.selectAfterServiceRecordList(afterServiceRecord);

            // 编辑返回属性
            orderListResponse.setOrderDetailId(detail.getId());
            orderListResponse.setOrderDetailCode(detail.getCode());
            orderListResponse.setOrderMasterId(detail.getOrderMasterId());
            orderListResponse.setOrderMasterCode(detail.getOrderMasterCode());
            orderListResponse.setGoodsName(goods.getGoodsName());
            orderListResponse.setGoodsLogoUrl(goods.getGoodsImgUrl());
            orderListResponse.setDiscountMoney(financialDetail.getDiscountMoney());
            orderListResponse.setTotalMoney(financialDetail.getTotalMoney());
            orderListResponse.setWorkerName(workerName);
            orderListResponse.setWorkerPhone(worker == null ? "" : worker.getPhone());
            orderListResponse.setCustomerName(customerAddress.getName());
            orderListResponse.setCustomerPhone(customerAddress.getPhone());
            orderListResponse.setOrderStatus(detail.getOrderStatus());
            orderListResponse.setPayStatus(orderMaster.getPayStatus());
            orderListResponse.setPayType(orderMaster.getPayType());
            orderListResponse.setStandardList(standardList);
            orderListResponse.setAddress(completeAddress);
            orderListResponse.setServerTime(detail.getRevTime());
            orderListResponse.setExpectTimeStart(detail.getExpectTimeStart());
            orderListResponse.setExpectTimeEnd(detail.getExpectTimeEnd());
            orderListResponse.setExpectTimeStartFront(detail.getExpectTimeStart());
            orderListResponse.setExpectTimeEndFront(detail.getExpectTimeEnd());
            orderListResponse.setWorkBeginTime(detail.getWorkBeginTime());
            orderListResponse.setWorkFinishTime(detail.getWorkFinishTime());
            orderListResponse.setClockInLocation(detail.getClockInLocation());
            orderListResponse.setRemark(goods.getRemark());
            orderListResponse.setCustomerRemark(orderMaster.getRemark());
            orderListResponse.setOrderType(detail.getOrderType());
            orderListResponse.setTimeout(detail.getTimeout());
            orderListResponse.setChangeMoney(changeMoney);
//            orderListResponse.setAfterServiceRecordList(afterServiceRecordList);
            orderListResponse.setUpdateTime(detail.getUpdateTime());
            orderListResponse.setShelveStatus(detail.getShelveStatus());
            orderListResponse.setLedgerAccountStatus(detail.getLedgerAccountStatus());
//            orderListResponse.setDrawCashId(detail.getDrawCashId());
            orderListResponse.setDrawCashTime(detail.getDrawCashTime());
            orderListResponse.setDrawCashStatus(detail.getDrawCashStatus());
            orderListResponse.setArrivalTime(detail.getArrivalTime());
            orderListResponses.add(orderListResponse);
        });
        return voDataTable(orderListResponses, list);
    }

    @PostMapping("/after/list")
    @ResponseBody
    public TableDataInfo afterServiceList(@RequestBody OrderDetail orderDetail) {
        AfterServiceRecord afterServiceRecord = new AfterServiceRecord();
        afterServiceRecord.setExcludeAfterServiceFinished(Boolean.TRUE);
        List<AfterServiceRecord> afterServiceRecordList = afterServiceRecordService.selectAfterServiceRecordList(afterServiceRecord);
        Map<Long, List<AfterServiceRecord>> detailRecordMap = afterServiceRecordList.stream().collect(Collectors.groupingBy(record -> record.getOrderDetailId()));
        // 踢重后的子单ids
        List<Long> detailIds = afterServiceRecordList.stream().map(AfterServiceRecord::getOrderDetailId).distinct().collect(Collectors.toList());
        StringBuilder orderDetailIds = new StringBuilder();
        detailIds.forEach(id -> {
            orderDetailIds.append(id).append(",");
        });
        String ids = orderDetailIds.toString();
        if (StringUtils.isNotEmpty(ids)) {
            orderDetail.setOrderDetailIds(ids.substring(0, ids.length() - 1));
        } else {
            orderDetail.setOrderDetailIds("0");
        }
        startPage();
        List<OrderListResponse> orderListResponses = new ArrayList<>();
        List<OrderDetail> list = orderDetailService.selectOrderDetailList(orderDetail);
        list.forEach(detail -> {

            // 主单信息
            OrderMaster orderMaster = orderMasterService.selectById(detail.getOrderMasterId());
            // 初始化属性
            OrderListResponse orderListResponse = new OrderListResponse();
            List<OrderStandard> standardList = new ArrayList<>();

            // 师傅信息
            Worker worker = workerService.selectById(detail.getWorkerId());
            WorkerCertification workerRealInfo = null;
            String workerName = "";
            if (worker != null) {
                // 师傅实名信息
                workerRealInfo = workerCertificationService.selectByWorkerId(orderMaster.getWorkerId());
                workerName = workerRealInfo == null ? worker.getName() : workerRealInfo.getName();
            }

            // 消费者信息
//            Customer customer = customerService.selectByCustomerId(detail.getCustomerId());

            // 商品规格及信息
            List<OrderGoods> orderStandardList = orderGoodsService.selectByOrderDetailId(detail.getId());

            // 商品信息
            GoodsStandard goodsStandard = goodsStandardService.selectById(orderStandardList.get(0).getGoodsStandardId());

            Goods goods = goodsService.selectById(goodsStandard.getGoodsId());

            // 财务信息
            FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(detail.getId());
            BigDecimal detailPayMoney = financialDetail.getPayMoney();

            // 查询子单加价记录
            FinancialChangeRecord financialChangeRecord = financialChangeRecordService.selectNotPayRecordByDetailId(detail.getId());
            BigDecimal changeMoney = financialChangeRecord == null ? BigDecimal.ZERO : financialChangeRecord.getChangeMoney();
            // 查询子单加价记录
//            FinancialChangeRecord changeRecordQry = new FinancialChangeRecord();
//            changeRecordQry.setOrderDetailId(detail.getId());
//            List<FinancialChangeRecord> financialChangeRecords = financialChangeRecordService.selectFinancialChangeRecordList(changeRecordQry);
//            if (CollectionUtils.isNotEmpty(financialChangeRecords)) {
//                detailPayMoney = detailPayMoney.add(financialChangeRecords.get(0).getChangeMoney());
//            }

            // 地址信息
            CustomerAddress customerAddress = addressService.selectByCustomerAddressId(orderMaster.getAddressId());
            SysArea sysArea = sysAreaService.selectById(customerAddress.getCountryId());
            String completeAddress = sysArea.getMergerName().replaceAll(",", "") + customerAddress.getAddress();

            for (OrderGoods orderGoods : orderStandardList) {
                OrderStandard orderStandard = new OrderStandard();
                orderStandard.setStandardName(orderGoods.getGoodsName());
                orderStandard.setStandardNum(orderGoods.getGoodsNum());
                orderStandard.setServerNum(orderGoods.getServerGoodsNum());
                orderStandard.setFinishTime(orderGoods.getFinishTime());
                orderStandard.setWaitServerNum(orderGoods.getGoodsNum() - orderGoods.getServerGoodsNum());
                standardList.add(orderStandard);
            }

            if (this.checkIsOnlyServer(orderMaster.getId(), detail.getWorkerId())) {
                FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(detail.getOrderMasterId());
                BigDecimal workerFee = financialMaster.getPayMoney();
                List<FinancialDetail> financialDetailList = financialDetailService.selectByFinancialMasterId(financialMaster.getId());
                for (FinancialDetail param : financialDetailList) {
                    if (!detail.getWorkerId().equals(param.getPayeeId())) {
                        workerFee = workerFee.subtract(param.getPayMoney());
                    }
                }
                orderListResponse.setPayMoney(workerFee);
                orderListResponse.setIsOnlyServ(Boolean.TRUE);
            } else {
                orderListResponse.setPayMoney(detailPayMoney);
                orderListResponse.setIsOnlyServ(Boolean.FALSE);
            }


            // 编辑返回属性
            orderListResponse.setOrderDetailId(detail.getId());
            orderListResponse.setOrderDetailCode(detail.getCode());
            orderListResponse.setOrderMasterId(detail.getOrderMasterId());
            orderListResponse.setOrderMasterCode(detail.getOrderMasterCode());
            orderListResponse.setGoodsName(goods.getGoodsName());
            orderListResponse.setGoodsLogoUrl(goods.getGoodsImgUrl());
            orderListResponse.setDiscountMoney(financialDetail.getDiscountMoney());
            orderListResponse.setTotalMoney(financialDetail.getTotalMoney());
            orderListResponse.setWorkerName(workerName);
            orderListResponse.setWorkerPhone(worker == null ? "" : worker.getPhone());
            orderListResponse.setCustomerName(customerAddress.getName());
            orderListResponse.setCustomerPhone(customerAddress.getPhone());
            orderListResponse.setOrderStatus(detail.getOrderStatus());
            orderListResponse.setPayStatus(orderMaster.getPayStatus());
            orderListResponse.setPayType(orderMaster.getPayType());
            orderListResponse.setStandardList(standardList);
            orderListResponse.setAddress(completeAddress);
            orderListResponse.setServerTime(detail.getRevTime());
            orderListResponse.setExpectTimeStart(detail.getExpectTimeStart());
            orderListResponse.setExpectTimeEnd(detail.getExpectTimeEnd());
            orderListResponse.setExpectTimeStartFront(detail.getExpectTimeStart());
            orderListResponse.setExpectTimeEndFront(detail.getExpectTimeEnd());
            orderListResponse.setWorkBeginTime(detail.getWorkBeginTime());
            orderListResponse.setWorkFinishTime(detail.getWorkFinishTime());
            orderListResponse.setRemark(goods.getRemark());
            orderListResponse.setCustomerRemark(orderMaster.getRemark());
            orderListResponse.setOrderType(detail.getOrderType());
            orderListResponse.setTimeout(detail.getTimeout());
            orderListResponse.setAfterServiceRecordList(detailRecordMap.get(detail.getId()));
            orderListResponse.setChangeMoney(changeMoney);
            orderListResponses.add(orderListResponse);
        });
        return voDataTable(orderListResponses, list);
    }

    @Log(title = "详细订单管理", businessType = BusinessType.EXPORT)
    @RequiresPermissions("order:detail:export")
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(OrderDetail orderDetail) {
        List<OrderDetail> list = orderDetailService.selectOrderDetailList(orderDetail);
        ExcelUtil<OrderDetail> util = new ExcelUtil<>(OrderDetail.class);
        return util.exportExcel(list, "详细订单数据");
    }

    @RequiresPermissions("order:detail:remove")
    @Log(title = "详细订单管理", businessType = BusinessType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        try {
            return toAjax(orderDetailService.deleteOrderDetailByIds(ids));
        } catch (Exception e) {
            return error(e.getMessage());
        }
    }

    /**
     * 修改详细订单
     */
    @RequiresPermissions("order:detail:edit")
    @GetMapping("/edit/{orderDetailId}")
    public String edit(@PathVariable("orderDetailId") Long orderDetailId, ModelMap mmap) {
        mmap.put("orderDetail", orderDetailService.selectById(orderDetailId));
        return prefix + "/edit";
    }

    /**
     * 修改保存详细订单
     */
    @RequiresPermissions("order:detail:edit")
    @Log(title = "详细订单管理", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(@Validated OrderDetail orderDetail) {
        if (UserConstants.ORDER_CODE_NOT_UNIQUE.equals(orderDetailService.checkOrderDetailCodeUnique(orderDetail))) {
            return error("修改详细订单'" + orderDetail.getCode() + "'失败，详细订单编码已存在");
        }
        orderDetail.setUpdateBy(getLoginName());
        return toAjax(orderDetailService.updateOrderDetail(orderDetail));
    }

    /**
     * 修改保存详细订单
     */
    @PostMapping("/app/edit")
    @ResponseBody
    public AjaxResult appEdit(@RequestBody OrderDetail orderDetail) {
        if (UserConstants.ORDER_CODE_NOT_UNIQUE.equals(orderDetailService.checkOrderDetailCodeUnique(orderDetail))) {
            return error("修改详细订单'" + orderDetail.getCode() + "'失败，详细订单编码已存在");
        }
        if (StringUtils.isNotEmpty(orderDetail.getClockInLocation())) {
            OrderDetail model = orderDetailService.selectById(orderDetail.getId());
            Customer customer = customerService.selectByCustomerId(model.getCustomerId());
            // 通知师傅新订单
            try {
                Map<String, Object> params = new HashMap<>();
                params.put("thing1", "师傅打卡通知");
                params.put("thing5", "请确认师傅已到达!");
                wxMsgService.sendWxMsg(customer.getOpenId(), WxMsgEnum.CUSTOMER_ORDER, params);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return toAjax(orderDetailService.updateOrderDetail(orderDetail));
    }

    /**
     * 校验详细订单编码
     */
    @PostMapping("/checkOrderDetailCodeUnique")
    @ResponseBody
    public String checkOrderDetailCodeUnique(OrderDetail orderDetail) {
        return orderDetailService.checkOrderDetailCodeUnique(orderDetail);
    }

    /**
     * 消费者确认完成子订单
     *
     * @param orderDetailId 子订单ID
     */
    @PostMapping("/finish")
    @ResponseBody
    public AjaxResult finish(Long orderDetailId) {
        logger.info("消费者确认完成子订单,orderDetailId={}", orderDetailId);
        try {
            orderDetailService.finish(orderDetailId);
        } catch (BaseAdaPayException e) {
            logger.error(e.getMessage(), e);
            return AjaxResult.error("操作失败，请稍后重试");
        }
        return AjaxResult.success();
    }

    /**
     * 消费者申请取消子订单
     *
     * @param orderDetailId 子订单ID
     */
    @PostMapping("/cancel")
    @ResponseBody
    public AjaxResult applyForCancel(Long orderDetailId) throws BaseAdaPayException {
        logger.info("消费者申请取消子订单,orderDetailId={}", orderDetailId);
        orderDetailService.applyForCancel(orderDetailId);
        return AjaxResult.success();
    }

    /**
     * 师傅审核取消子订单申请
     *
     * @param orderDetailId 子订单ID
     * @param agree         0=不同意 1=同意
     */
    @PostMapping("/cancel/agree")
    @ResponseBody
    public AjaxResult cancelAgree(Long orderDetailId, Integer agree) throws BaseAdaPayException {
        logger.info("师傅审核取消子订单申请,orderDetailId={},agree={}", orderDetailId, agree);
        orderDetailService.cancelAgree(orderDetailId, agree);
        return AjaxResult.success();
    }

    /**
     * 师傅发起完单
     *
     * @param request 完单发起请求对象
     */
    @PostMapping("/app/applyFinishOrder")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult applyFinishOrder(@RequestBody OrderProcessRequest request) {
        logger.info("师傅发起完单,orderDetailId={}", request.getOrderDetailId());
        // 判断是否有未完成的售后记录,如果有则不允许完单
        AfterServiceRecord unfinishedByOrderDetailId = afterServiceRecordService.getUnfinishedByOrderDetailId(request.getOrderDetailId());
        if(unfinishedByOrderDetailId != null){
            return AjaxResult.error("存在未处理完的售后,不允许申请完单!");
        }
        // 判断工单状态是否为服务中以及是否已支付
        OrderDetail orderDetail = orderDetailService.selectById(request.getOrderDetailId());
        OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
        if (orderDetail.getOrderStatus().equals(OrderStatus.FINISH_CHECK.code())) {
            return AjaxResult.success("发起成功");
        }
        if (orderDetail.getOrderStatus() != OrderStatus.SERVER.code()
                || !orderMaster.getPayStatus().equals(PayStatus.PAID.getCode())) {
            return AjaxResult.error("未支付订单或非服务中订单，发起完单失败");
        }

        Worker worker = workerService.selectById(orderDetail.getWorkerId());
        Assert.notNull(worker, "师傅不存在 workerId=" + orderDetail.getWorkerId());
        WorkerCertification wcc = workerCertificationService.selectByWorkerId(orderDetail.getWorkerId());
        if (wcc == null || wcc.getStatus() == null || wcc.getStatus() != 1) {
            return AjaxResult.error("师傅未认证，请先去认证哦！");
        }

        // 存储完单图
        List<GoodsImgs> finishImgObjList = new ArrayList<>();
        for (String imgUrl : request.getFinishImgList()) {
            GoodsImgs finishImgObj = new GoodsImgs();
            finishImgObj.setGoodsId(0L);
            finishImgObj.setImgType(ImgType.FINISH_IMG.getId());
            finishImgObj.setImgUrl(imgUrl);
            finishImgObj.setRemark(String.valueOf(request.getOrderDetailId()));
            finishImgObjList.add(finishImgObj);
        }
        int insertedRows = goodsImgsService.batchInsert(finishImgObjList);
        Assert.isTrue(insertedRows > 0, "完单图入库失败，request=" + request);

        // 存储评价标签
        if (CollectionUtils.isNotEmpty(request.getAssessLabels())) {
            request.getAssessLabels().forEach(label -> {
                OrderAssessLabel orderAssessLabel = new OrderAssessLabel();
                orderAssessLabel.setLabelId(label);
                orderAssessLabel.setOrderId(request.getOrderDetailId());
                int insertLabelRow = orderAssessLabelService.insertOrderAssessLabel(orderAssessLabel);
                Assert.isTrue(insertLabelRow > 0, "，labelId=" + label);
            });
        }

        // 修改子单状态为完单待确认状态，更新完单时间
        OrderDetail updateOrderDetail = new OrderDetail();
        updateOrderDetail.setId(request.getOrderDetailId());
        updateOrderDetail.setWorkFinishTime(new Date());
        updateOrderDetail.setOrderStatus(OrderStatus.FINISH_CHECK.code());
        updateOrderDetail.setRemark(request.getRemark());
        int affectedRow = orderDetailService.updateOrderDetail(updateOrderDetail);
        Assert.isTrue(affectedRow == 1, "子订单修改失败，orderDetail=" + orderDetail);

        OrderBehavior orderBehavior = new OrderBehavior()
                .setOrderMasterId(orderMaster.getId()).setOrderMasterCode(orderMaster.getCode())
                .setOrderDetailId(orderDetail.getId()).setOrderDetailCode(orderDetail.getCode())
                .setWorkerId(worker.getWorkerId()).setWorkerName(worker.getName())
                .setBehavior(OrderBehaviorEnum.FINISH_ORDER);
        orderBehaviorService.insert(orderBehavior);

        Customer customer = customerService.selectByCustomerId(orderDetail.getCustomerId());
        // 通知师傅新订单
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("thing1", "师傅完单通知");
            params.put("thing5", "请确认师傅工作已完成!");
            wxMsgService.sendWxMsg(customer.getOpenId(), WxMsgEnum.CUSTOMER_ORDER, params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success("发起成功");
    }

    /**
     * 拒绝订单
     * 后台管理系统使用，可控制权限
     */
    @PostMapping("/reject")
    @ResponseBody
    public AjaxResult reject(OrderDetail orderDetail) {
        return rejectDetailOrder(orderDetail);
    }

    /**
     * 拒绝订单
     */
    @PostMapping("/app/order/reject")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult rejectDetailOrder(@RequestBody OrderDetail orderDetail) {
        // 查询订单信息
        OrderDetail od = this.orderDetailService.selectById(orderDetail.getId());
        OrderMaster om = orderMasterService.selectById(od.getOrderMasterId());
        Worker masterWorker = workerService.selectById(om.getWorkerId());
        Worker worker = workerService.selectById(od.getWorkerId());
        // 删除子单
        orderDetailService.deleteOrderDetailByIds(orderDetail.getId().toString());
        FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(od.getId());
        // 财务子单金额返还给主单
        FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(od.getOrderMasterId());
        financialMaster.setServerMoney(financialMaster.getServerMoney().add(financialDetail.getPayMoney()));
        financialMasterService.updateFinancialMaster(financialMaster);
        // 删除子财务单
        financialDetailService.deleteFinancialDetailByOrderDetailId(orderDetail.getId());
        // 退回旧商品
//        List<OrderGoods> goodsList = orderGoodsService.selectByOrderDetailId(orderDetail.getId());
//        goodsList.forEach(orderGoods -> {
//            List<OrderGoods> masterGoods = orderGoodsService.selectByOrderMasterId(od.getOrderMasterId());
//            masterGoods.forEach(master->{
//                if(master.getGoodsStandardId().equals(orderGoods.getGoodsStandardId())){
//                    master.setServerGoodsNum(master.getServerGoodsNum()-orderGoods.getGoodsNum());
//                }
//                orderGoodsService.updateOrderGoods(master);
//            });
//        });
        // 删除派单记录
        orderGoodsService.deleteByOrderDetailId(orderDetail.getId());
        OrderMaster orderMaster2Update = new OrderMaster();
        orderMaster2Update.setId(od.getOrderMasterId());
        orderMaster2Update.setOrderStatus(OrderStatus.PLAIN.code());
        // 查询是否还有派单记录，没有的话需要重置主单是否自己承接的字段为NULL
        List<OrderGoods> existOrderGoods = orderGoodsService.selectByOrderMasterId(od.getOrderMasterId());
        if (CollectionUtils.isNotEmpty(existOrderGoods)) {
            orderMaster2Update.setResetAllSelfAssigned(true);
        }
        // 更新主单是否全部派完
        orderMaster2Update.setHasDispatchedAll(0);
        orderMasterService.updateOrderMaster(orderMaster2Update);

        OrderBehavior orderBehavior = new OrderBehavior()
                .setOrderMasterId(om.getId()).setOrderMasterCode(om.getCode())
                .setWorkerId(worker.getWorkerId()).setWorkerName(worker.getName())
                .setBehavior(OrderBehaviorEnum.REFUSE_ORDER);
        orderBehaviorService.insert(orderBehavior);

        // 通知师傅新订单
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("thing1", "订单被拒通知");
            params.put("thing5", "订单被拒绝,请及时处理!");
            wxMsgService.sendWxMsg(masterWorker.getOpenId(), WxMsgEnum.ORDER_PLAN, params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success();
    }

    @PostMapping("/app/change/price")
    @ResponseBody
    public AjaxResult changePrice(@Valid @RequestBody OrderChangePriceRequest request) {
        try {
            Assert.notNull(request.getChangeMoney(), "报价不能为空");
            return toAjax(orderDetailService.changePrice(request.getOrderDetailId(), request.getChangeMoney(), request.getType(), request.getRemark()));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error("改价失败!");
        }
    }

    @PostMapping("/app/getChangePrice")
    @ResponseBody
    public AjaxResult getChangePrice(@Valid @RequestBody OrderChangePriceRequest request) {
        try {
            return AjaxResult.success(orderDetailService.getChangedPriceRecord(request.getOrderDetailId()));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(ExceptionUtil.getExceptionMessage(e));
            return AjaxResult.error("查询改价失败!");
        }
    }

    private boolean checkIsOnlyServer(Long orderMasterId, Long workId) {
        // 找出原单的数量
        List<OrderGoods> orderGoodsList = orderGoodsService.selectByOrderMasterId(orderMasterId);
        // 找出原单关联的细单的商品数量
        List<OrderDetail> orderDetailList = orderDetailService.selectByOrderMasterId(orderMasterId);
        for (OrderDetail detail : orderDetailList) {
            // 非一个师傅接单
            if (!workId.equals(detail.getWorkerId())) {
                return false;
            }
            // 子单数量
            List<OrderGoods> orderDetailGoodsList = orderGoodsService.selectByOrderDetailId(detail.getId());
            // 计算剩余未分配的商品数量
            for (OrderGoods detailGoods : orderDetailGoodsList) {
                for (OrderGoods masterGoods : orderGoodsList) {
                    if (Objects.equals(masterGoods.getGoodsStandardId(), detailGoods.getGoodsStandardId())) {
                        masterGoods.setGoodsNum(masterGoods.getGoodsNum() - detailGoods.getGoodsNum());
                    }
                }
            }
        }
        // 有单派完.
        for (OrderGoods orderGoods : orderGoodsList) {
            if (orderGoods.getGoodsNum() > 0) {
                return false;
            }
        }
        return true;
    }
}
