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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.superdesk.uniorder.common.constants.ResponseMsgConstants;
import cn.superdesk.uniorder.common.enums.invoice.supplier.InvoiceApplySupplierInvoiceProgressingStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.supplier.InvoiceApplySupplierMakeInvoiceStatusEnum;
import cn.superdesk.uniorder.common.exception.utils.ExceptionUtils;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
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.invoice.supplier.InvoiceApplySupplier;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderForm;
import cn.superdesk.uniorder.dto.param.invoice.supplier.status.InvoiceApplySupplierOpCommonDimAccountingOrderItem;
import cn.superdesk.uniorder.dubbo.consumer.invoice.supplier.InvoiceApplySupplierDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.supplier.InvoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService;
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.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 = "InvoiceApplySupplier - MakeInvoiceStatus", tags = {"InvoiceApplySupplier - MakeInvoiceStatus"})
@Slf4j
@RestController
@RequestMapping("/invoice/apply/supplier/score/state/makeInvoiceStatus")
public class InvoiceApplySupplierScoreFieldMakeInvoiceStatusController extends BaseController {

    @Autowired
    private InvoiceApplySupplierDubboConsumerService                       invoiceApplySupplierDubboConsumerService;
    @Autowired
    private InvoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService invoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService;

    @ApiOperation(value = "InvoiceApplySupplier - MakeInvoiceStatus - 操作 供应商|商户 未开票 侨城汇-运营 从对账单 一键分票操作后创建的开票申请  状态改变为 未开票_0")
    @RequestMapping(value = "/opInit/{id}", method = RequestMethod.POST)
    @ResponseBody
    public R<?> opInit(@PathVariable("id") Long id) {

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

        try {
            InvoiceApplySupplier entity = invoiceApplySupplierDubboConsumerService.findById(id);
            invoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService.opInit(getToken(), entity);
            result.setSuccess(true);

        } catch (Exception e) {

            result.setSuccess(false);
            result.setMessage(ResponseMsgConstants.ERROR_UNKNOW);
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }
        return result;
    }

    @ApiOperation(value = "InvoiceApplySupplier - MakeInvoiceStatus - 操作 供应商|商户 op确认开票 已开票 状态改变为 已开票_1")
    @RequestMapping(value = "/opComplete/{id}", method = RequestMethod.POST)
    @ResponseBody
    public R<?> opComplete(@PathVariable("id") Long id) {

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

        try {
            InvoiceApplySupplier entity = invoiceApplySupplierDubboConsumerService.findById(id);
            invoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService.opComplete(getToken(), entity);
            result.setSuccess(true);

        } catch (Exception e) {

            result.setSuccess(false);
            result.setMessage(ResponseMsgConstants.ERROR_UNKNOW);
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }
        return result;
    }

    @ApiOperation(value = "InvoiceApplySupplier - MakeInvoiceStatus - 对账单维度 - 操作 供应商|商户 op确认开票 已开票 状态改变为 已开票_1")
    @RequestMapping(value = "/opComplete/dim/accountingOrder", method = RequestMethod.POST)
    @ResponseBody
    public R<?> opCompleteDimAccountingOrder(@RequestBody InvoiceApplySupplierOpCommonDimAccountingOrderForm form) {

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

        // TODO 简单验证

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

        try {

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

            if (StrUtil.isBlank(form.getAccountingOrderSn())) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据 [参数] 异常");
            }

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

            List<InvoiceApplySupplier> entitysExistDb = invoiceApplySupplierDubboConsumerService.findByAccountingOrderSn(form.getAccountingOrderSn());

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

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


            /****************************************** 提交的数量与数据库数量 start ******************************************/

            List<Long> invoiceApplyIds = form.getInvoiceApplySupplierList().stream().map(InvoiceApplySupplierOpCommonDimAccountingOrderItem::getInvoiceApplyId).collect(Collectors.toList());

            List<InvoiceApplySupplier> entitysQueryBySubmit = invoiceApplySupplierDubboConsumerService.findByIds(invoiceApplyIds);

            if (CollUtil.isEmpty(invoiceApplyIds)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据 [完整性] 异常");
            }
            if (CollUtil.isEmpty(entitysQueryBySubmit)) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据 [完整性] 异常");
            }
            if (entitysExistDb.size() != entitysQueryBySubmit.size()) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据 [完整性] 异常");
            }

            /****************************************** 提交的数量与数据库数量 start ******************************************/


            /****************************************** 申请状态 start ******************************************/

            List<Integer> invoiceProgressingStatus = entitysQueryBySubmit.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getInvoiceStatus())).map(InvoiceApplySupplier::getInvoiceStatus).collect(Collectors.toList());

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

            InvoiceApplySupplierInvoiceProgressingStatusEnum invoiceApplySupplierInvoiceProgressingStatusEnum = InvoiceApplySupplierInvoiceProgressingStatusEnum.get(invoiceProgressingStatus.get(0));
            if (invoiceApplySupplierInvoiceProgressingStatusEnum != InvoiceApplySupplierInvoiceProgressingStatusEnum.待开票) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据 [申请状态] 异常, 要求 [申请状态] 为 [待开票]");
            }

            /****************************************** 申请状态 start ******************************************/


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

            List<Integer> makeInvoiceStatus = entitysQueryBySubmit.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getMakeInvoiceStatus())).map(InvoiceApplySupplier::getMakeInvoiceStatus).collect(Collectors.toList());

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

            InvoiceApplySupplierMakeInvoiceStatusEnum invoiceApplySupplierMakeInvoiceStatusEnum = InvoiceApplySupplierMakeInvoiceStatusEnum.get(makeInvoiceStatus.get(0));
            if (invoiceApplySupplierMakeInvoiceStatusEnum != InvoiceApplySupplierMakeInvoiceStatusEnum.未开票) {
                return ResponseResultOuterUtils.createErrorResult("500", "提交的数据 [开票状态] 异常, 要求 [开票状态] 为 [未开票]");
            }

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

            invoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService.opComplete(getToken(), entitysQueryBySubmit, form);
            result.setSuccess(true);

        } catch (Exception e) {

            result.setSuccess(false);
            result.setMessage(ResponseMsgConstants.ERROR_UNKNOW);
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 基于对账单维度的批量操作不在这边 opBecomeInvalid
     * https://ordertest.octlife.cn/web/invoice/apply/supplier/opBecomeInvalid/dim/accountingOrder
     *
     * @param id
     * @return
     */
    @Deprecated
    @ApiOperation(value = "InvoiceApplySupplier - MakeInvoiceStatus - 操作 供应商|商户 op撤消开票 已撤消 状态改变为 已撤消_2")
    @RequestMapping(value = "/opBecomeInvalid/{id}", method = RequestMethod.POST)
    @ResponseBody
    public R<?> opBecomeInvalid(@PathVariable("id") Long id) {

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

        try {
            InvoiceApplySupplier entity = invoiceApplySupplierDubboConsumerService.findById(id);
            invoiceApplySupplierFieldMakeInvoiceStatusDubboConsumerService.opBecomeInvalid(getToken(), entity);
            result.setSuccess(true);

        } catch (Exception e) {

            result.setSuccess(false);
            result.setMessage(ResponseMsgConstants.ERROR_UNKNOW);
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }
        return result;
    }


}
