package cn.superdesk.uniorder.controller.invoice.customer.state;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.superdesk.uniorder.common.bizScene.invoice.common.InvoiceTypeScene;
import cn.superdesk.uniorder.common.bizScene.invoice.customer.InvoiceApplyCustomerScene;
import cn.superdesk.uniorder.common.constants.ResponseMsgConstants;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderInvoiceApplyStatusEnum;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderTypeDimEnum;
import cn.superdesk.uniorder.common.enums.accounting.customer.AccountingOrderCustomerAccountingStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerInvoiceProgressingStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerMailTickStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerMakeInvoiceStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerReceiveInvoiceStatusEnum;
import cn.superdesk.uniorder.common.exception.utils.ExceptionUtils;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.common.numerical.AnStringUtils;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.rest.response.ResponseResultOuterUtils;
import cn.superdesk.uniorder.controller.base.BaseController;
import cn.superdesk.uniorder.dao.entity.accounting.score.customer.AccountingScoreCustomer;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApply;
import cn.superdesk.uniorder.dto.param.invoice.customer.InvoiceApplyCustomerQueryCriteriaV2_1;
import cn.superdesk.uniorder.dto.param.invoice.customer.status.*;
import cn.superdesk.uniorder.dto.vo.accounting.score.customer.AccountingOrderScoreCustomerListItemVo;
import cn.superdesk.uniorder.dto.vo.invoice.customer.InvoiceApplyCustomerPageVo;
import cn.superdesk.uniorder.dto.vo.invoice.customer.mailTickStatus.InvoiceManagerCustomerOpMailTickStatusPageVo;
import cn.superdesk.uniorder.dubbo.consumer.accounting.customer.AccountingScoreCustomerDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.customer.InvoiceApplyCustomerDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.customer.state.InvoiceApplyFieldMailTickStatusDubboConsumerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 寄票登记部分 - 简易状态机 星型结构
 * @Author: linjinyu
 * @CreateDate: 10/12/20 4:28 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 10/12/20 4:28 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Api(value = "积分结算v2.2-发票单-寄票登记部分-InvoiceApply-MailTickStatus", tags = {"积分结算v2.2-发票单-寄票登记部分-InvoiceApply-MailTickStatus"})
@Slf4j
@RestController
@RequestMapping("/invoice/apply/customer/score/state/mailTickStatus/V2_2")
public class InvoiceApplyCustomerScoreFieldMailTickStatusV2_2Controller extends BaseController {

    @Autowired
    private InvoiceApplyCustomerDubboConsumerService            invoiceApplyCustomerDubboConsumerService;
    @Autowired
    private InvoiceApplyFieldMailTickStatusDubboConsumerService invoiceApplyFieldMailTickStatusDubboConsumerService;

    @Autowired
    private AccountingScoreCustomerDubboConsumerService accountingScoreCustomerDubboConsumerService;

    /**
     * 积分结算 > 发票管理 > 寄票登记 > op寄票登记|op修改寄票 页面初始化
     *
     * @param accountingOrderSn
     * @return
     */
    @ApiOperation(value = "op寄票登记|op修改寄票-页面初始化 v2.2", notes = "积分结算v2.2-20220429")
    @RequestMapping(value = "/opInit/{accountingOrderSn}", method = RequestMethod.POST)
    @ResponseBody
    public R<InvoiceManagerCustomerOpMailTickStatusPageVo> opInit(@PathVariable("accountingOrderSn") String accountingOrderSn) {

        try {


//            InvoiceApply entity = invoiceApplyCustomerDubboConsumerService.findById(id);
//            invoiceApplyFieldMailTickStatusDubboConsumerService.opInit(entity, getToken());
//            result.setSuccess(true);

            List<InvoiceApplyCustomerPageVo> pageVoList = invoiceApplyCustomerDubboConsumerService.findInvoiceListFocusScoreV2_1(
                    InvoiceApplyCustomerQueryCriteriaV2_1
                            .builder()
                            .invoiceProgressingStatusSelected(Arrays.asList(
                                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.待开票.getKey(),
                                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.待领票.getKey(),
                                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.待寄票.getKey(),
                                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.待回款.getKey(),
                                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.已完成.getKey()
                            ))
                            .accountingOrderSn(accountingOrderSn)
                            .build(),
                    getToken()
            );

            AccountingOrderScoreCustomerListItemVo accountingOrderScoreCustomerVo = accountingScoreCustomerDubboConsumerService.getAccountingOrderListByAccountingOrderSn(accountingOrderSn, getToken());

            return ResponseResultOuterUtils.createSuccesResult(
                    "init",
                    InvoiceManagerCustomerOpMailTickStatusPageVo
                            .builder()
                            .pageVoList(pageVoList)
                            .accountingOrder(accountingOrderScoreCustomerVo)
                            .build()
            );

        } catch (Exception e) {

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();

            return ResponseResultOuterUtils.createErrorResult("500", ResponseMsgConstants.ERROR_UNKNOW);
        }

    }

    /**
     * op确认寄票
     * 只适用于v2.1逻辑 v2.2逻辑变更
     * v2.1 逻辑为 发票文件 与 快递信息 都是挂在 发票单上
     * v2.2 逻辑为 发票文件 与 快递信息 都是挂在 对账单上
     * mark by linjinyu at 20220429
     *
     * @param formV2_2
     * @return
     */
    @ApiOperation(value = "op寄票登记-op确认寄票 v2.2 InvoiceApply-MailTickStatus-op 已邮寄 1 - 对账单维度", notes = "积分结算v2.2-20220429")
    @RequestMapping(value = "/opComplete/dim/accountingOrder", method = RequestMethod.POST)
    @ResponseBody
    public R<?> opCompleteDimAccountingOrder(@RequestBody OpMailTickStatusFormV2_2 formV2_2) { // 以对账单维度自动补全 - 20220111

        R<?> result = new R<>();

        // TODO 简单验证

        if (CollUtil.isEmpty(formV2_2.getSubmitList())) {
            return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
        }

        try {

            /****************************************** 对账单编号 start ******************************************/

            List<String> accountingOrderSns = formV2_2.getSubmitList()
                    .stream()
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getAccountingOrderSn()))
                    .map(OpChangeStatusBaseItem::getAccountingOrderSn)
                    .collect(Collectors.toList());

            if (CollUtil.isEmpty(accountingOrderSns)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
            }

            if (accountingOrderSns.size() > 1) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常");
            }

            /**************************************** 对账单 start ****************************************/

            String accountingOrderSn = accountingOrderSns.get(0);

            AccountingScoreCustomer accountingScoreCustomer = accountingScoreCustomerDubboConsumerService.findByAccountingOrderSn(accountingOrderSn);

            if (ObjectUtil.isNull(accountingScoreCustomer)) {
                return ResponseResultOuterUtils.createErrorResult("500", "对账单数据异常");
            }

            if (accountingScoreCustomer.getAccountingStatus().compareTo(AccountingOrderCustomerAccountingStatusEnum.已确认.getKey()) != 0) {
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单状态发生变更，请检查");
            }

            if (accountingScoreCustomer.getInvoiceStatus().compareTo(AccountingOrderInvoiceApplyStatusEnum.全部申请.getKey()) != 0) {
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单申请状态未全部申请，请返回检查");
            }


            /**************************************** 对账单 start ****************************************/

//（2）服务端需判断：
//·该对账单状态为“已确认”，否则不允许确认寄票，1.5s提示“该对账单状态发生变更，请检查”；
//·该对账单的申请状态为“全部申请”，否则不允许确认寄票，1.5s提示“该对账单申请状态未全部申请，请返回检查”；
//·该对账单下所有开票申请均存在且有效，否则不允许确认寄票，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；
//·该对账单下所有开票申请的申请状态为“待寄票/待回款”，否则不允许确认寄票，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；
//满足以上保存条件，即确认寄票成功： // mark by linjinyu at 202203312209 需求文本有误 确认领票 -> 确认寄票
//①开票方式为“深圳航信电子发票”的开票申请：其相关快递公司/快递单号/寄票人/寄票时间等数据及状态，不作任何更新改动，仍为原数据；
//②开票方式为“线下开票”的开票申请：
//·对应开票申请的申请状态变更为“待回款”；
//·对应开票申请的寄票状态变更为“已寄票”；
//·快递公司&快递单号写入到对应的开票申请中，快递公司以ID关联存储，可能未来存在快递公司名称修改；
//·对应开票申请的寄票人姓名和时间记录为当前操作人姓名和时间；
//·注：当前页面无“已红冲/已作废”的开票申请，因此“已红冲/已作废”的开票申请的状态和数据不作任何变动；
//③1.5s提示“寄票成功”，关闭当前页签，自动跳转到“发票管理”列表页面，列表数据重新获取；


            /****************************************** 开票申请 - 数据库 start ******************************************/

            List<InvoiceApply> entitysExistDb = invoiceApplyCustomerDubboConsumerService.findByAccountingOrderSn(accountingOrderSns.get(0), AccountingOrderTypeDimEnum.积分订单);

            if (CollUtil.isEmpty(entitysExistDb)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[000]");
            }

            /**************************************** 开票状态 start ****************************************/

            List<Integer> makeInvoiceStatusExistDb = entitysExistDb
                    .stream()
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getMakeInvoiceStatus()))
                    .map(InvoiceApply::getMakeInvoiceStatus)
                    .collect(Collectors.toList());

            /**************************************** 领票状态 start ****************************************/

            List<Integer> receiveInvoiceStatusExistDb = entitysExistDb
                    .stream()
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getReceiveInvoiceStatus()))
                    .map(InvoiceApply::getReceiveInvoiceStatus)
                    .collect(Collectors.toList());

            /**************************************** 寄票状态 start ****************************************/

            List<Integer> mailTickStatusExistDb = entitysExistDb
                    .stream()
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getMailTickStatus()))
                    .map(InvoiceApply::getMailTickStatus)
                    .collect(Collectors.toList());

            /****************************************** 开票申请 - 前端提交 start ******************************************/

            List<Long> invoiceApplyIds = formV2_2.getSubmitList()
                    .stream()
                    .map(OpMailTickStatusFormInnerListItemV2_2::getInvoiceApplyId)
                    .collect(Collectors.toList());

            List<InvoiceApply> entitysQueryBySubmit = invoiceApplyCustomerDubboConsumerService.findByIds(invoiceApplyIds);
            List<InvoiceApply> entitysNeedOpMailTick = entitysQueryBySubmit
                    .stream()
                    .filter(o -> ArrayUtil.contains(InvoiceTypeScene.modesV2_1_Array_SceneNeedOpMailTick(), o.getInvoiceMode()))
                    .collect(Collectors.toList());

            if (CollUtil.isEmpty(invoiceApplyIds)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[001]");
            }
            if (CollUtil.isEmpty(entitysQueryBySubmit)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[002]");
            }
            // 前端没有因为有一个是线上而少传一个，所以这里不能用过滤后只有线下的
            if (invoiceApplyIds.size() != entitysQueryBySubmit.size()) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[003]");
            }


            /**************************************** 只处理线下开票情况 start ****************************************/


            /**************************************** op确认寄票 - 改逻辑 20220510 start ****************************************/

            /**************************************** |---- 检查 申请状态 start ****************************************/

//            https://docs.qq.com/doc/DYUZOREhreVhiVlZL
//·该对账单下所有开票申请的开票状态均为“已开票”，否则不允许确认领票[!!!寄票!!!]，1.5s提示“该对账单所有开票申请的开票状态存在部分未开票”；【20220510新增】
//·该对账单下所有有效的开票申请的领票状态存在全部为“已领票”，否则不允许确认寄票，1.5提示“该对账单所有开票申请的领票状态存在部分未领票”；【20220510新增】
//·该对账单下所有有效的开票申请的寄票状态存在全部/部分为“未寄票”，否则不允许确认寄票，1.5提示“该对账单所有开票申请的寄票状态全部已寄票，无需寄票”；【20220510新增】
//·该对账单下所有开票申请的申请状态为“待寄票/待回款”，否则不允许确认寄票，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；【20220510去掉此判断】


            // 逻辑 ·该对账单下所有开票申请的开票状态均为“已开票”，否则不允许确认领票[!!!寄票!!!]，1.5s提示“该对账单所有开票申请的开票状态存在部分未开票”；【20220510新增】 start

            if (CollUtil.isEmpty(makeInvoiceStatusExistDb)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[开票状态] 未知");
            } else if (makeInvoiceStatusExistDb.size() == 1) {

                // 开票状态 唯一的情况
                InvoiceApplyCustomerMakeInvoiceStatusEnum invoiceApplyCustomerMakeInvoiceStatusEnumExistDb = InvoiceApplyCustomerMakeInvoiceStatusEnum.get(makeInvoiceStatusExistDb.get(0));

                // 意思是 如果这个唯一情况 的开票状态 为 待开票 开票中
                if (ArrayUtil.contains(
                        InvoiceApplyCustomerScene.statusV2_1_Array_MakeInvoiceSceneOpReceiveStateCheck(),
                        invoiceApplyCustomerMakeInvoiceStatusEnumExistDb.getKey())
                ) {
                    return ResponseResultOuterUtils.createErrorResult("500", "该对账单所有开票申请的开票状态存在部分未开票");
                }

            } else if (makeInvoiceStatusExistDb.size() > 1) {
                // 意思是 不唯一情况 是不可能 达到 该对账单下所有开票申请的开票状态均为 已开票
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单所有开票申请的开票状态存在部分未开票");
            } else {
            }

            // 逻辑 ·该对账单下所有开票申请的开票状态均为“已开票”，否则不允许确认领票[!!!寄票!!!]，1.5s提示“该对账单所有开票申请的开票状态存在部分未开票”；【20220510新增】   end

            // 逻辑 ·该对账单下所有有效的开票申请的领票状态存在全部为“已领票”，否则不允许确认寄票，1.5提示“该对账单所有开票申请的领票状态存在部分未领票”；【20220510新增】 start

            if (CollUtil.isEmpty(receiveInvoiceStatusExistDb)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[领票状态] 未知");
            } else if (receiveInvoiceStatusExistDb.size() == 1) {

                // 领票状态 唯一的情况
                InvoiceApplyCustomerReceiveInvoiceStatusEnum invoiceApplyCustomerReceiveInvoiceStatusExistDb = InvoiceApplyCustomerReceiveInvoiceStatusEnum.get(receiveInvoiceStatusExistDb.get(0));

                if (invoiceApplyCustomerReceiveInvoiceStatusExistDb != InvoiceApplyCustomerReceiveInvoiceStatusEnum.已领票) {
                    return ResponseResultOuterUtils.createErrorResult("500", "该对账单所有开票申请的领票状态存在部分未领票");
                }

            } else if (receiveInvoiceStatusExistDb.size() > 1) {

                // 领票状态 不唯一的情况 好像不用做了 ---- 前置条件 开票状态均为-已开票
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单所有开票申请的领票状态存在部分未领票");

            } else {

            }

            // 逻辑 ·该对账单下所有有效的开票申请的领票状态存在全部为“已领票”，否则不允许确认寄票，1.5提示“该对账单所有开票申请的领票状态存在部分未领票”；【20220510新增】   end

            // 逻辑 ·该对账单下所有有效的开票申请的寄票状态存在全部/部分为“未寄票”，否则不允许确认寄票，1.5提示“该对账单所有开票申请的寄票状态全部已寄票，无需寄票”；【20220510新增】start


            if (CollUtil.isEmpty(mailTickStatusExistDb)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[寄票状态] 未知");
            } else if (mailTickStatusExistDb.size() == 1) {

                // 寄票状态 唯一的情况
                InvoiceApplyCustomerMailTickStatusEnum invoiceApplyCustomerMailTickStatusExistDb = InvoiceApplyCustomerMailTickStatusEnum.get(mailTickStatusExistDb.get(0));

                if (invoiceApplyCustomerMailTickStatusExistDb == InvoiceApplyCustomerMailTickStatusEnum.已寄票) {
                    return ResponseResultOuterUtils.createErrorResult("500", "该对账单所有开票申请的寄票状态全部已寄票，无需寄票");
                }

            } else if (mailTickStatusExistDb.size() > 1) {

                // 寄票状态 不唯一的情况 好像不用做了 ---- 前置条件 领票状态均为-已领票

            } else {

            }

            // 逻辑 ·该对账单下所有有效的开票申请的寄票状态存在全部/部分为“未寄票”，否则不允许确认寄票，1.5提示“该对账单所有开票申请的寄票状态全部已寄票，无需寄票”；【20220510新增】  end

            // 逻辑去掉 ·该对账单下所有开票申请的申请状态为“待寄票/待回款”，否则不允许确认寄票，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；【20220510去掉此判断】start

//            // 错误 在混合的情况下是错的
////            List<Integer> mailTickStatus = entitysExistDb.stream()
//            // 在混合的情况是下是排除 线上开票方式
//            List<Integer> invoiceProgressingStatus = entitysNeedOpMailTick.stream()
//                    // 排除线上
//                    .filter(AnLamdaUtils.distinctByKey(o -> o.getInvoiceStatus()))
//                    .map(InvoiceApply::getInvoiceStatus)
//                    .collect(Collectors.toList());
//
//            if (CollUtil.isEmpty(invoiceProgressingStatus)) {
//                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[申请状态]");
//            }
//            if (invoiceProgressingStatus.size() > 1) {
//                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[申请状态]");
//            }
//
//            //·该对账单下所有开票申请的申请状态为“待寄票/待回款”，否则不允许确认寄票，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；
//            InvoiceApplyCustomerInvoiceProgressingStatusEnum invoiceApplyCustomerInvoiceProgressingStatusEnum = InvoiceApplyCustomerInvoiceProgressingStatusEnum.get(invoiceProgressingStatus.get(0));
//
//            Integer[] invoiceProgressingStatusNeed = {
//                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.待寄票.getKey(),
//                    InvoiceApplyCustomerInvoiceProgressingStatusEnum.待回款.getKey()
//            };
//
//            if (!ArrayUtil.contains(invoiceProgressingStatusNeed, invoiceApplyCustomerInvoiceProgressingStatusEnum.getKey())) {
//                return ResponseResultOuterUtils.createErrorResult("500", "该对账单的开票申请数据发生变更，请返回检查");
//            }

            // 逻辑去掉 ·该对账单下所有开票申请的申请状态为“待寄票/待回款”，否则不允许确认寄票，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；【20220510去掉此判断】start


            /**************************************** |---- 检查 申请状态   end ****************************************/


            /**************************************** |---- 检查 寄票状态 start ****************************************/

//            // 错误 在混合的情况下是错的
////            List<Integer> mailTickStatus = entitysExistDb.stream()
//            // 在混合的情况是下是排除 线上开票方式
//            List<Integer> mailTickStatus = entitysOnlyOffLine.stream()
//                    // 排除线上
////                    .filter(o -> o.getInvoiceMode().equals(InvoiceTypeMoudelXModeEnum.线下开票.getKey()))
//                    .filter(AnLamdaUtils.distinctByKey(o -> o.getMailTickStatus())).map(InvoiceApply::getMailTickStatus).collect(Collectors.toList());
//
//            if (CollUtil.isEmpty(mailTickStatus)) {
//                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[寄票状态]");
//            }
//            if (mailTickStatus.size() > 1) {
//                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[寄票状态] ");
//            }
//
//            InvoiceApplyCustomerMailTickStatusEnum invoiceApplyCustomerMailTickStatusEnum = InvoiceApplyCustomerMailTickStatusEnum.get(mailTickStatus.get(0));
//
//            if (invoiceApplyCustomerMailTickStatusEnum != InvoiceApplyCustomerMailTickStatusEnum.未邮寄) {
////				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常,要求状态为[未邮寄]");
//                return ResponseResultOuterUtils.createErrorResult("500", "该对账单的开票申请数据发生变更，请返回检查");
//            }

            /**************************************** |---- 检查 寄票状态   end ****************************************/


            /**************************************** 只处理线下开票情况   end ****************************************/

            // 在混合的情况是下是排除 线上开票方式中(深圳航信电子票而已)
            // 注意 如果 form 发票单列表 中 发票号为空的情况是不会把 快递信息 填充到 发票单中 只会推进流程


            List<OpMailTickStatusFormInnerListItemV2_1> submitList = new ArrayList<>();

            formV2_2.getSubmitList().forEach(formV2_2InnerItem -> {
                submitList.add(
                        OpMailTickStatusFormInnerListItemV2_1
                                .builder()

                                .expressCompanyId(formV2_2.getExpressCompanyId())
                                .expressNo(formV2_2.getExpressNo())
                                .invoiceNumber(Arrays.asList("不要在意,只有此字段不为空时,才会更新快递信息,此字段不会更新到发票单中"))

                                .accountingOrderId(formV2_2InnerItem.getAccountingOrderId())
                                .accountingOrderSn(formV2_2InnerItem.getAccountingOrderSn())

                                .invoiceApplyId(formV2_2InnerItem.getInvoiceApplyId())
                                .invoiceApplySn(formV2_2InnerItem.getInvoiceApplySn())

                                .build()
                );
            });

            log.info("List<OpMailTickStatusFormInnerListItemV2_1> submitList \n{}", JSONUtil.toJsonPrettyStr(submitList));

            OpMailTickStatusFormV2_1 formV2_1 = OpMailTickStatusFormV2_1
                    .builder()
                    .submitList(submitList)
                    .build();

            invoiceApplyFieldMailTickStatusDubboConsumerService.opCompleteV2_1(entitysNeedOpMailTick, formV2_1, getToken());

            // 对账单 发递信息记录
            int ret = accountingScoreCustomerDubboConsumerService.opExpressRecord(formV2_2, accountingScoreCustomer, getToken());

            if (ret > 0) {
                return ResponseResultOuterUtils.createSuccesResult("寄票成功");
            } else {
                return ResponseResultOuterUtils.createErrorResult("500", "寄票操作失败");
            }

        } catch (Exception e) {

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();

            return ResponseResultOuterUtils.createErrorResult("500", ResponseMsgConstants.ERROR_UNKNOW);
        }

    }


    /**
     * op修改寄票 -> op确认修改
     *
     * @param formV2_2
     * @return
     */
    @ApiOperation(value = "op修改寄票-op确认修改 v2.2 InvoiceApply-MailTickStatus-op 已邮寄 1 - 对账单维度", notes = "积分结算v2.2-20220429")
    @RequestMapping(value = "/opEdit/dim/accountingOrder", method = RequestMethod.POST)
    @ResponseBody
    public R<String> opEditDimAccountingOrder(@RequestBody OpMailTickStatusFormV2_2 formV2_2) { // 以对账单维度自动补全 - 20220111

        // TODO 简单验证

        if (CollUtil.isEmpty(formV2_2.getSubmitList())) {
            return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[参数001]");
        }

        try {

            /****************************************** 对账单编号 start ******************************************/

            List<String> accountingOrderSns = formV2_2.getSubmitList()
                    .stream()
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getAccountingOrderSn()))
                    .map(OpChangeStatusBaseItem::getAccountingOrderSn)
                    .collect(Collectors.toList());

            if (CollUtil.isEmpty(accountingOrderSns)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[对账单001]");
            }

            if (accountingOrderSns.size() > 1) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[对账单002]");
            }

            /**************************************** 对账单 start ****************************************/

            String accountingOrderSn = accountingOrderSns.get(0);

            AccountingScoreCustomer accountingScoreCustomer = accountingScoreCustomerDubboConsumerService.findByAccountingOrderSn(accountingOrderSn);

            if (ObjectUtil.isNull(accountingScoreCustomer)) {
                return ResponseResultOuterUtils.createErrorResult("500", "对账单数据异常[对账单003]");
            }

            if (accountingScoreCustomer.getAccountingStatus().compareTo(AccountingOrderCustomerAccountingStatusEnum.已确认.getKey()) != 0) {
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单状态发生变更，请检查");
            }

            if (accountingScoreCustomer.getInvoiceStatus().compareTo(AccountingOrderInvoiceApplyStatusEnum.全部申请.getKey()) != 0) {
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单申请状态未全部申请，请返回检查");
            }


            /**************************************** 对账单   end ****************************************/

//（2）服务端需判断：
//·该对账单状态为“已确认”，否则不允许确认修改，1.5s提示“该对账单状态发生变更，请检查”；
//·该对账单的申请状态为“全部申请”，否则不允许确认修改，1.5s提示“该对账单申请状态未全部申请，请返回检查”；
//·该对账单下所有开票申请均存在且有效，否则不允许确认修改，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；
//·该对账单下所有开票申请的申请状态均为“待回款”，否则不允许确认修改，1.5s提示“该对账单的开票申请数据发生变更，请返回检查”；
//满足以上保存条件，即确认修改成功：
//①开票方式为“深圳航信电子发票”的开票申请：其相关快递公司/快递单号/寄票人/寄票时间等数据及状态，不作任何更新改动，仍为原数据；
//②开票方式为“线下开票”的开票申请：
//·更新开票申请中的“快递公司/快递单号/上传文件”数据；
//·更新寄票人姓名和时间记录为当前操作人姓名和时间；
//·更新该开票申请修改人和时间记录为当前操作人姓名和时间；
//·注：当前页面无“已红冲/已作废”的开票申请，因此“已红冲/已作废”的开票申请的状态和数据不作任何变动；
//·申请状态/寄票状态保持原有状态不变；
//·其他数据不作更新
//③1.5s提示“修改寄票成功”，关闭当前页签，自动跳转到“发票管理”列表页面，列表数据重新获取；

            /****************************************** 开票申请 - 数据库 start ******************************************/

            List<InvoiceApply> entitysExistDb = invoiceApplyCustomerDubboConsumerService.findByAccountingOrderSn(accountingOrderSns.get(0), AccountingOrderTypeDimEnum.积分订单);

            if (CollUtil.isEmpty(entitysExistDb)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[库数据000]");
            }

            /****************************************** 开票申请 - 前端提交 start ******************************************/

            List<Long> invoiceApplyIds = formV2_2.getSubmitList()
                    .stream()
                    .map(OpMailTickStatusFormInnerListItemV2_2::getInvoiceApplyId)
                    .collect(Collectors.toList());

            List<InvoiceApply> entitysQueryBySubmit = invoiceApplyCustomerDubboConsumerService.findByIds(invoiceApplyIds);
            List<InvoiceApply> entitysNeedOpMailTick = entitysQueryBySubmit
                    .stream()
                    .filter(o -> ArrayUtil.contains(InvoiceTypeScene.modesV2_1_Array_SceneNeedOpMailTickEdit(), o.getInvoiceMode()))
                    .collect(Collectors.toList());

            if (CollUtil.isEmpty(invoiceApplyIds)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[发票单001]");
            }
            if (CollUtil.isEmpty(entitysQueryBySubmit)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[发票单002]");
            }
            // 前端没有因为有一个是线上而少传一个，所以这里不能用过滤后只有线下的
            if (invoiceApplyIds.size() != entitysQueryBySubmit.size()) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[发票单003]");
            }


            /**************************************** |---- 检查 申请状态 start ****************************************/

            // 在混合的情况下是错的 ---- 现在是对的 ---- mark by linjinyu at 20220507

            // 【【结算中心-测试环境】积分结算-发票管理-开票方式为“深圳航信电子发票”，修改寄票-【确认修改】提示“数据异常”】
            // https://www.tapd.cn/33003868/bugtrace/bugs/view?bug_id=1133003868001005073
            // 又双叕冲突 纯电的情况 ---- mark by linjinyu at 20220507

            //
            List<Integer> invoiceProgressingStatusExistDb = entitysExistDb
                    .stream()
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getInvoiceStatus()))
                    .map(InvoiceApply::getInvoiceStatus)
                    .collect(Collectors.toList());


            // 在混合的情况是下是排除 不需要寄票的 开票方式
            List<Integer> invoiceProgressingStatusNeedOpMailTick = entitysNeedOpMailTick
                    .stream()
                    // 排除线上
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getInvoiceStatus()))
                    .map(InvoiceApply::getInvoiceStatus)
                    .collect(Collectors.toList());

            /**************************************** 冲突的逻辑在这里写 start ****************************************/

            if (CollUtil.isEmpty(invoiceProgressingStatusNeedOpMailTick)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[发票单][申请状态][异常001]");
            }
            if (invoiceProgressingStatusNeedOpMailTick.size() > 1) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常[发票单][申请状态][异常002]");
            }

            /**************************************** 冲突的逻辑在这里写 start ****************************************/


            InvoiceApplyCustomerInvoiceProgressingStatusEnum invoiceApplyCustomerInvoiceProgressingStatusEnumNeedOpMailTick = InvoiceApplyCustomerInvoiceProgressingStatusEnum.get(invoiceProgressingStatusNeedOpMailTick.get(0));

            if (invoiceApplyCustomerInvoiceProgressingStatusEnumNeedOpMailTick != InvoiceApplyCustomerInvoiceProgressingStatusEnum.待回款) {
                return ResponseResultOuterUtils.createErrorResult("500", "该对账单的开票申请数据发生变更，请返回检查");
            }

            /**************************************** |---- 检查 申请状态   end ****************************************/


            /**************************************** |---- 检查 寄票状态 start ****************************************/

//            // 错误 在混合的情况下是错的
////            List<Integer> mailTickStatus = entitysExistDb.stream()
//            // 在混合的情况是下是排除 线上开票方式
//            List<Integer> mailTickStatus = entitysOnlyOffLine.stream()
//                    // 排除线上
////                    .filter(o -> o.getInvoiceMode().equals(InvoiceTypeMoudelXModeEnum.线下开票.getKey()))
//                    .filter(AnLamdaUtils.distinctByKey(o -> o.getMailTickStatus())).map(InvoiceApply::getMailTickStatus).collect(Collectors.toList());
//
//            if (CollUtil.isEmpty(mailTickStatus)) {
//                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[寄票状态]");
//            }
//            if (mailTickStatus.size() > 1) {
//                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常，[寄票状态] ");
//            }
//
//            InvoiceApplyCustomerMailTickStatusEnum invoiceApplyCustomerMailTickStatusEnum = InvoiceApplyCustomerMailTickStatusEnum.get(mailTickStatus.get(0));
//
//            if (invoiceApplyCustomerMailTickStatusEnum != InvoiceApplyCustomerMailTickStatusEnum.未邮寄) {
////				return ResponseResultOuterUtils.createErrorResult("500", "提交的数据异常,要求状态为[未邮寄]");
//                return ResponseResultOuterUtils.createErrorResult("500", "该对账单的开票申请数据发生变更，请返回检查");
//            }

            /**************************************** |---- 检查 寄票状态   end ****************************************/


//            OpMailTickStatusFormV2_1 formV2_1 = AnBeanUtils.copy(formV2_2, OpMailTickStatusFormV2_1.class);
//            formV2_1.getSubmitList().forEach(formV2_1InnerItem -> {
//
//                formV2_1InnerItem.setExpressCompanyId(formV2_2.getExpressCompanyId());
//                formV2_1InnerItem.setExpressNo(formV2_2.getExpressNo());
//                formV2_1InnerItem.setInvoiceNumber(Arrays.asList("不要在意,只有此字段不为空时,才会更新快递信息,此字段不会更新到发票单中"));
//
//            });

            List<OpMailTickStatusFormInnerListItemV2_1> submitList = new ArrayList<>();

            formV2_2.getSubmitList().forEach(formV2_2InnerItem -> {
                submitList.add(
                        OpMailTickStatusFormInnerListItemV2_1
                                .builder()
                                .expressCompanyId(formV2_2.getExpressCompanyId())
                                .expressNo(formV2_2.getExpressNo())
                                .invoiceNumber(Arrays.asList("不要在意,只有此字段不为空时,才会更新快递信息,此字段不会更新到发票单中"))
                                .build()
                );
            });

            OpMailTickStatusFormV2_1 formV2_1 = OpMailTickStatusFormV2_1.builder()
                    .submitList(submitList)
                    .build();

            // 在混合的情况是下是排除 线上开票方式
            invoiceApplyFieldMailTickStatusDubboConsumerService.opCompleteV2_1(entitysNeedOpMailTick, formV2_1, getToken());

            int ret = accountingScoreCustomerDubboConsumerService.opExpressRecord(formV2_2, accountingScoreCustomer, getToken());

            if (ret > 0) {
                return ResponseResultOuterUtils.createSuccesResult("修改寄票成功");
            } else {
                return ResponseResultOuterUtils.createErrorResult("500", "修改寄票操作失败");
            }

        } catch (Exception e) {

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();

            return ResponseResultOuterUtils.createErrorResult("500", ResponseMsgConstants.ERROR_UNKNOW);
        }

    }


    //	attachmentUploadfilesUids
//	attachment_upload_files_uids

    @ApiOperation(value = "op寄票登记|op修改寄票 v2.2 绑定附件(binding attachment)-对账单")
    @RequestMapping(value = "/opBindingAttachment/accountingOrder", method = RequestMethod.POST)
    @ResponseBody
    public R<String> opBindingAttachmentToAccountingOrder(@RequestBody OpCommonStatusBindingAttachmentForm form) {

        try {

            AccountingScoreCustomer entity = accountingScoreCustomerDubboConsumerService.findByAccountingOrderSn(form.getAccountingOrderSn());

            if (ObjectUtil.isNull(entity)) {
                return ResponseResultOuterUtils.createErrorResult("500", "资源不存在");
            }

            AccountingScoreCustomer forUpdate = new AccountingScoreCustomer();
            forUpdate.setId(entity.getId());

            if (CollUtil.isEmpty(form.getUids())) {
                forUpdate.setAttachmentUploadFilesUids("");
            } else {
                forUpdate.setAttachmentUploadFilesUids(AnStringUtils.stringListConvertToString(form.getUids()));
            }

            int ret = accountingScoreCustomerDubboConsumerService.opUpdateByPrimaryKeySelective(forUpdate, getToken());

            if (ret > 0) {
                return ResponseResultOuterUtils.createSuccesResult();
            } else {
                return ResponseResultOuterUtils.createErrorResult("500", "操作失败");
            }

        } catch (Exception e) {

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();

            return ResponseResultOuterUtils.createErrorResult("500", ResponseMsgConstants.ERROR_UNKNOW);
        }


    }


}
