package cn.superdesk.uniorder.service.invoice.supplier.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.superdesk.uniorder.common.enums.invoice.supplier.InvoiceApplySupplierInvoiceProgressingStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.supplier.InvoiceApplySupplierPayOffAccountStatusEnum;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.common.security.dto.LoginSysUser;
import cn.superdesk.uniorder.dao.entity.invoice.supplier.InvoiceApplySupplier;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderForm;
import cn.superdesk.uniorder.executor.scheduler.kafka._thirdpart.qchjc.QchjcStatementKafkaEventPublisher;
import cn.superdesk.uniorder.executor.scheduler.kafka._thirdpart.qchjc.dto.accounting.supplier.QchjcSupplierStatementEvent;
import cn.superdesk.uniorder.executor.scheduler.kafka._thirdpart.qchjc.dto.accounting.supplier.QchjcSupplierStatementEventMultipleStructVo;
import cn.superdesk.uniorder.executor.scheduler.kafka._thirdpart.qchjc.dto.accounting.supplier.QchjcSupplierStatementEventSingleStructVo;
import cn.superdesk.uniorder.pattern.state.invoice.supplier.invoiceApplySupplier.payoffAccountStatus.context.InvoiceApplySupplierFieldPayoffAccountStatusContext;
import cn.superdesk.uniorder.service.accounting.unified.supplier.AccountingUnifiedSupplierService;
import cn.superdesk.uniorder.service.invoice.supplier.InvoiceApplySupplierFieldPayoffAccountStatusService;
import cn.superdesk.uniorder.service.invoice.supplier.InvoiceApplySupplierService;
import cn.superdesk.uniorder.service.invoice.supplier.InvoiceApplySupplierXGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
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
 */
@Slf4j
@Service
public class InvoiceApplySupplierFieldPayoffAccountStatusServiceImpl implements InvoiceApplySupplierFieldPayoffAccountStatusService {

    @Autowired
    private InvoiceApplySupplierService       invoiceApplySupplierService;
    @Autowired
    private InvoiceApplySupplierXGoodsService invoiceApplySupplierXGoodsService;

    @Autowired
    private AccountingUnifiedSupplierService accountingUnifiedSupplierService;

    /**************************************** superdesk-uniorder-executor start ****************************************/

    @Autowired
    private QchjcStatementKafkaEventPublisher qchjcStatementEventPublisher;

    /**************************************** superdesk-uniorder-executor   end ****************************************/

    /****************************************** 状态机 公共方法 机内使用 实际流转 重用 start
     * @return******************************************/

    // 状态流转为 待付款(0, "待付款")
    @Override
    public int opInitByStateMachine(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {

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

        // TODO 更新状态逻辑...

        forUpdate.setPayoffAccountStatus(InvoiceApplySupplierPayOffAccountStatusEnum.待付款.getKey());

        return invoiceApplySupplierService.updateInvoiceApplySupplierByPrimaryKeySelective(forUpdate);
    }

    // 状态流转为 付款中(10, "付款中")
    @Override
    public int opRegulatoryPipelineByStateMachine(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {

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

        // TODO 更新状态逻辑...

        forUpdate.setPayoffAccountStatus(InvoiceApplySupplierPayOffAccountStatusEnum.付款中.getKey());

        return invoiceApplySupplierService.updateInvoiceApplySupplierByPrimaryKeySelective(forUpdate);
    }

    // 状态流转为 付款中(10, "付款中")
    @Override
    public int opRegulatoryPipelineByStateMachine(List<InvoiceApplySupplier> entitys, InvoiceApplySupplierOpCommonDimAccountingOrderForm form, LoginSysUser loginSysUser) {

        DateTime now = DateUtil.date();

        entitys.forEach(entity -> {

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

            // TODO 更新状态逻辑...

            forUpdate.setPayoffAccountStatus(InvoiceApplySupplierPayOffAccountStatusEnum.付款中.getKey());
            forUpdate.setPayoffAccountTime(now);
            forUpdate.setPayoffAccountUserId(loginSysUser.getSysUserId());
            // 付款(结清)登记部分 - 付款(结清)登记方式记录:0-初始;10-手动;11-流水;
            forUpdate.setPayoffAccountModeRecord(10);

            // 进入下一个流程
            forUpdate.setInvoiceStatus(InvoiceApplySupplierInvoiceProgressingStatusEnum.待付款.getKey());

            invoiceApplySupplierService.updateInvoiceApplySupplierByPrimaryKeySelective(forUpdate);
        });

        List<Long> processInvoiceApplyIds = entitys
                .stream()
                .filter(AnLamdaUtils.distinctByKey(o -> o.getId()))
                .map(o -> o.getId())
                .collect(Collectors.toList());
        List<Long> processAccountingOrderIds = invoiceApplySupplierXGoodsService.getAffectedAccountingOrderIdsByInvoiceApplyIds(processInvoiceApplyIds);

        processAccountingOrderIds.forEach(accountingOrderId -> {
            accountingUnifiedSupplierService.updateFieldInvoiceStatus(accountingOrderId, InvoiceApplySupplierInvoiceProgressingStatusEnum.待付款, loginSysUser);
            accountingUnifiedSupplierService.updateFieldBackAccountStatus(accountingOrderId, InvoiceApplySupplierPayOffAccountStatusEnum.付款中, loginSysUser);
        });

        return 1;

    }

    // 状态流转为 部分付款(1, "部分付款")
    @Override
    public int opPartByStateMachine(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {

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

        // TODO 更新状态逻辑...

        forUpdate.setPayoffAccountStatus(InvoiceApplySupplierPayOffAccountStatusEnum.部分付款.getKey());

        return invoiceApplySupplierService.updateInvoiceApplySupplierByPrimaryKeySelective(forUpdate);
    }

    // 状态流转为 已付款(2, "已付款")
    @Override
    public int opCompleteByStateMachine(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {

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

        // TODO 更新状态逻辑...

        forUpdate.setPayoffAccountStatus(InvoiceApplySupplierPayOffAccountStatusEnum.已付款.getKey());

        return invoiceApplySupplierService.updateInvoiceApplySupplierByPrimaryKeySelective(forUpdate);
    }

    // 状态流转为 已付款(2, "已付款")
    @Override
    public int opCompleteByStateMachine(List<InvoiceApplySupplier> entitys, InvoiceApplySupplierOpCommonDimAccountingOrderForm form, LoginSysUser loginSysUser) {


        DateTime now = DateUtil.date();

        int ret = 0;

        entitys.forEach(entity -> {

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

            // TODO 更新状态逻辑...

            forUpdate.setPayoffAccountStatus(InvoiceApplySupplierPayOffAccountStatusEnum.已付款.getKey());
            forUpdate.setPayoffAccountTime(now);
            forUpdate.setPayoffAccountUserId(loginSysUser.getSysUserId());
            // 付款(结清)登记部分 - 付款(结清)登记方式记录:0-初始;10-手动;11-流水;
            forUpdate.setPayoffAccountModeRecord(10);

            // 进入下一个流程
            forUpdate.setInvoiceStatus(InvoiceApplySupplierInvoiceProgressingStatusEnum.已完成.getKey());

            invoiceApplySupplierService.updateInvoiceApplySupplierByPrimaryKeySelective(forUpdate);
        });

        List<Long> processInvoiceApplyIds = entitys
                .stream()
                .filter(AnLamdaUtils.distinctByKey(o -> o.getId()))
                .map(o -> o.getId())
                .collect(Collectors.toList());
        List<Long> processAccountingOrderIds = invoiceApplySupplierXGoodsService.getAffectedAccountingOrderIdsByInvoiceApplyIds(processInvoiceApplyIds);

        processAccountingOrderIds.forEach(accountingOrderId -> {
            accountingUnifiedSupplierService.updateFieldInvoiceStatus(accountingOrderId, InvoiceApplySupplierInvoiceProgressingStatusEnum.已完成, loginSysUser);
            // TODO mark by linjinyu at 2022-06-21 11:14:41 - 呵呵，现在才发现的问题
//            【【结算中心-测试环境】供应商结算-京东对账-列表-对账单已完成付款操作，“付款状态”未更新】https://www.tapd.cn/33003868/bugtrace/bugs/view?bug_id=1133003868001005423
            accountingUnifiedSupplierService.updateFieldBackAccountStatus(accountingOrderId, InvoiceApplySupplierPayOffAccountStatusEnum.已付款, loginSysUser);
        });

        /**************************************** 触发事件点 start ****************************************/

        // 触发事件点;集采账单状态推送 TODO
        // 1. 来源于“企业商城”的对账单在**“供应商结算-货款管理-【确认付款】”成功时**：若该对账单的所有有效的开票申请的申请状态均为“已付款”时；（“付款中”状态无需同步。）

        List<QchjcSupplierStatementEventSingleStructVo> eventSingleStructVoList = new ArrayList<>();
        form.getInvoiceApplySupplierList().forEach(item -> {
            eventSingleStructVoList.add(
                    QchjcSupplierStatementEventSingleStructVo
                            .builder()
                            .accountingOrderId(form.getAccountingOrderId())
                            .accountingOrderSn(form.getAccountingOrderSn())
                            .invoiceApplyId(item.getInvoiceApplyId())
                            .invoiceApplySn(item.getInvoiceApplySn())
                            .build()
            );
        });
        qchjcStatementEventPublisher.supplierStatementEventPaymentStatusSync(
                QchjcSupplierStatementEvent
                        .builder()
                        .msg("供应商结算v2.3-货款管理-op发起付款-op确认付款")

                        .multipleStructVo(
                                QchjcSupplierStatementEventMultipleStructVo
                                        .builder()
                                        .items(eventSingleStructVoList)
                                        .build()
                        )

                        .loginSysUser(JSONUtil.toJsonStr(loginSysUser))
                        .touchTime(now)

                        .build()
        );

        /**************************************** 触发事件点   end ****************************************/


        return 1;

    }

    /****************************************** 状态机 公共方法 机内使用 实际流转 重用   end ******************************************/


    /****************************************** 状态机 外部使用 类门面 start ******************************************/

    // 状态流转为 待付款(0, "待付款")
    @Override
    public int opInit(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {
        InvoiceApplySupplierFieldPayoffAccountStatusContext context = new InvoiceApplySupplierFieldPayoffAccountStatusContext(entity, loginSysUser);
        return context.opInit();
    }

    // 状态流转为 付款中(10, "付款中")
    @Override
    public int opRegulatoryPipeline(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {
        InvoiceApplySupplierFieldPayoffAccountStatusContext context = new InvoiceApplySupplierFieldPayoffAccountStatusContext(entity, loginSysUser);
        return context.opRegulatoryPipeline();
    }

    // 状态流转为 付款中(10, "付款中")
    @Override
    public int opRegulatoryPipeline(List<InvoiceApplySupplier> entitys, InvoiceApplySupplierOpCommonDimAccountingOrderForm form, LoginSysUser loginSysUser) {
        InvoiceApplySupplierFieldPayoffAccountStatusContext context = new InvoiceApplySupplierFieldPayoffAccountStatusContext(entitys, form, loginSysUser);
        return context.opRegulatoryPipeline();
    }

    // 状态流转为 部分付款(1, "部分付款")
    @Override
    public int opPart(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {
        InvoiceApplySupplierFieldPayoffAccountStatusContext context = new InvoiceApplySupplierFieldPayoffAccountStatusContext(entity, loginSysUser);
        return context.opPart();
    }

    // 状态流转为 已付款(2, "已付款")
    @Override
    public int opComplete(InvoiceApplySupplier entity, LoginSysUser loginSysUser) {
        InvoiceApplySupplierFieldPayoffAccountStatusContext context = new InvoiceApplySupplierFieldPayoffAccountStatusContext(entity, loginSysUser);
        return context.opComplete();
    }

    // 状态流转为 已付款(2, "已付款")
    @Override
    public int opComplete(List<InvoiceApplySupplier> entitys, InvoiceApplySupplierOpCommonDimAccountingOrderForm form, LoginSysUser loginSysUser) {
        InvoiceApplySupplierFieldPayoffAccountStatusContext context = new InvoiceApplySupplierFieldPayoffAccountStatusContext(entitys, form, loginSysUser);
        return context.opComplete();
    }

    /****************************************** 状态机 外部使用 类门面   end ******************************************/
}
