package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.dao.mapper.BmsLogOperationMapper;
import com.prolog.rdc.tms.dao.mapper.ShipBillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.ShipBillFeeDetailMapper;
import com.prolog.rdc.tms.dao.mapper.ShipBillHeadMapper;
import com.prolog.rdc.tms.model.dto.*;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.vo.ShipBillQueryVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.ReconciliationManagementService;
import com.prolog.rdc.tms.util.ConvertorUtil;
import org.apache.ibatis.plugin.PluginException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

@Service
public class ReconciliationManagementServiceImpl implements ReconciliationManagementService {

    @Autowired
    private ShipBillHeadMapper shipBillHeadMapper;
    @Autowired
    private ShipBillDetailMapper detailMapper;
    @Autowired
    private ShipBillFeeDetailMapper feeDetailMapper;
    @Autowired
    private BmsLogOperationMapper logOperationMapper;
    @Autowired
    private ConvertorUtil convertorUtil;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Override
    public Page<ShipBillFeeListDTO> findList(ShipBillQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        vo.setUserType(user.getUserType());
        if (user.getUserType().equals(BmsConstant.USER_TYPE_CYS)) {
            vo.setCarrierId(Long.valueOf(user.getLoginUserCompanyInfo().getId()));
        }
        if (user.getUserType().equals(BmsConstant.USER_TYPE_ZY)) {
            if (user.getOwnedAllDataAuthFlag().equals(BmsConstant.USER_DEPARTMENT_AUTH_Y)) {
                vo.setDepartmentIds(user.getDepts().toArray(new String[0]));
                vo.setIsDept(BmsConstant.IS_DEPT_YES);
            } else {
                vo.setIsDept(BmsConstant.IS_DEPT_NO);
                vo.setDepartmentIds(user.getDepts().toArray(new String[0]));
                vo.setBranchIds(user.getWarehouses());
                vo.setCargoOwnerIds(user.getConsignors());
                // 客户
                vo.setCustomers(user.getCustomers());
                // 供应商
                vo.setSuppliers(user.getSuppliers());
            }
        }
        RestMessage<SySParameterDTO> parameterModel = maindataTmsResource.queryParameter();
        if (!parameterModel.isSuccess() || ObjectUtil.isEmpty(parameterModel.getData())) {
            throw new PluginException("获取系统参数异常");
        }
        Integer isReconciliation = parameterModel.getData().getIsReconciliation();
        if (isReconciliation.intValue() == 1) {
            vo.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_3);
        } else {
            vo.setSettlementStatus(BmsConstant.SETTLEMENT_STATUS_0);
        }
        List<Integer> checkSts = Lists.newArrayList();
        if (ObjectUtil.isNotEmpty(vo.getCheckStatus())) {
            checkSts.add(vo.getCheckStatus());
        } else {
            checkSts.add(0);
            checkSts.add(1);
        }
        vo.setCheckStatuses(checkSts);

        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<ShipBillFeeListDTO> feeList = shipBillHeadMapper.findFeeList(vo, user.getEnterpriseId());

        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.SHIPBILL_STATUS, // 运单状态
                BmsConstant.SHIPPER_TYPE, // 运输状态
                BmsConstant.ABNORMAL_STATUS, // 异常状态
                BmsConstant.ORDER_TYPE, // 订单类型
                BmsConstant.CONSIGNEE_TYPE, // 收货方类型
                BmsConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
                BmsConstant.SOURCE, // 来源
                BmsConstant.CHECK_STATUS, // 结算状态
                BmsConstant.SETTLEMENT_STATUS, // 核算状态
                BmsConstant.TEMPERATURE_REQUIREMENT// 温度要求
        });

        for (ShipBillFeeListDTO shipBillFeeListDTO : feeList) {
            shipBillFeeListDTO.setBillingSourceName(shipBillFeeListDTO.getBillingSource() == 1 ? "价格表生成" : "手工录入");
            shipBillFeeListDTO.setSourceName(shipBillFeeListDTO.getBillingSourceName());
            shipBillFeeListDTO.setSource(shipBillFeeListDTO.getBillingSource());
            shipBillFeeListDTO.setCheckStatusName(ConvertorUtil.getName(dicData, BmsConstant.CHECK_STATUS, String.valueOf(shipBillFeeListDTO.getCheckStatus())));
            shipBillFeeListDTO.setExpenseMemo(shipBillFeeListDTO.getMemo());
            shipBillFeeListDTO.setOrderTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_TYPE, String.valueOf(shipBillFeeListDTO.getOrderType())));
            shipBillFeeListDTO.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_BUSINESS_TYPE, String.valueOf(shipBillFeeListDTO.getOrderBusinessType())));
            shipBillFeeListDTO.setTemperatureRequirementName(ConvertorUtil.getName(dicData, BmsConstant.TEMPERATURE_REQUIREMENT, String.valueOf(shipBillFeeListDTO.getTemperatureRequirement())));
            shipBillFeeListDTO.setShipperTypeName(ConvertorUtil.getName(dicData, BmsConstant.SHIPPER_TYPE, String.valueOf(shipBillFeeListDTO.getShipperType())));
            shipBillFeeListDTO.setConsigneeTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONSIGNEE_TYPE, String.valueOf(shipBillFeeListDTO.getConsigneeType())));
            shipBillFeeListDTO.setDeliveryMethodTypeName(shipBillFeeListDTO.getDeliveryMethodType() == 1 ? "配送" : "自提");
            shipBillFeeListDTO.setTransportTypeName(shipBillFeeListDTO.getTransportType() == 1 ? "整车" : "零担");
            shipBillFeeListDTO.setStatusName(ConvertorUtil.getName(dicData, BmsConstant.SHIPBILL_STATUS, String.valueOf(shipBillFeeListDTO.getStatus())));
            shipBillFeeListDTO.setSourceName(ConvertorUtil.getName(dicData, BmsConstant.SOURCE, String.valueOf(shipBillFeeListDTO.getSource())));
            shipBillFeeListDTO.setSettlementStatusName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_STATUS, String.valueOf(shipBillFeeListDTO.getSettlementStatus())));
            shipBillFeeListDTO.setCarrierTypeName(shipBillFeeListDTO.getCarrierType() == 1 ? "承运商" : "司机");
            shipBillFeeListDTO.setShipperAddressInfo(shipBillFeeListDTO.getShipperProvinceName()+shipBillFeeListDTO.getShipperCityName());
            shipBillFeeListDTO.setConsigneeAddressInfo(shipBillFeeListDTO.getConsigneeProvinceName()+shipBillFeeListDTO.getConsigneeCityName());
            // 实际送达实际 - 实际启运实际 deliveryDate - startDate
            if (ObjectUtil.isNotEmpty(shipBillFeeListDTO.getDeliveryDate()) && ObjectUtil.isNotEmpty(shipBillFeeListDTO.getStartDate())) {
                long time1 = shipBillFeeListDTO.getDeliveryDate().getTime();
                long time2 = shipBillFeeListDTO.getStartDate().getTime();

                BigDecimal minutes = BigDecimal.valueOf((time2 - time1) / 1000 / 60);
                // 获取小时
                BigDecimal divide = minutes.divide(new BigDecimal(60), 5, RoundingMode.HALF_UP);
                shipBillFeeListDTO.setActualTime(divide.intValue());
            }
            shipBillFeeListDTO.setCostDate(shipBillFeeListDTO.getCostDate());
            shipBillFeeListDTO.setBillingStatusName(shipBillFeeListDTO.getBillingStatus() == 1?"计费成功":"未计费");
            shipBillFeeListDTO.setAbnormalStatusName(shipBillFeeListDTO.getAbnormalStatus() == 1 ? "异常" : "非异常");

            if (shipBillFeeListDTO.getCarrierType().intValue() == 2) {
                shipBillFeeListDTO.setCarrierName(shipBillFeeListDTO.getDriverName());
                shipBillFeeListDTO.setCarrierId(shipBillFeeListDTO.getDriverId());
                shipBillFeeListDTO.setCarrierCode(shipBillFeeListDTO.getDriverCode());
            }
        }
        return PageUtils.getPage(feeList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(List<String> ids) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsShipBillFeeDetailModel> detailModels = feeDetailMapper.findByIds(BmsShipBillFeeDetailModel.class, ids.toArray(), null);
        if (ObjectUtil.isEmpty(detailModels)) {
            throw new PluginException("获取费用信息失败");
        }
        for (BmsShipBillFeeDetailModel detailModel : detailModels) {
            if (detailModel.getCheckStatus() == 2) {
                throw new PluginException(String.format("费用单[%s]已对账确认！",detailModel.getExpenseName()));
            }
            if (detailModel.getCheckStatus() == 1 ) {
                throw new PluginException(String.format("费用单[%s]已对账提交！",detailModel.getExpenseName()));
            }
            detailModel.setCheckStatus(1);
            detailModel.setUpdateperson(user.getNickname());
            detailModel.setUpdatetime(DateUtil.date());
            feeDetailMapper.update(detailModel);

            // 日志操作
            BmsLogOperationModel logVO = new BmsLogOperationModel();
            logVO.setCreatetime(DateUtil.date());
            logVO.setCreateperson(user.getNickname());
            logVO.setEnterpriseId(user.getEnterpriseId());
            logVO.setEnterpriseName(user.getEnterpriseName());
            logVO.setOrderNo(detailModel.getShipbillNo());
            logVO.setLogMemo("对账提交");
            logVO.setLogType(3);
            logOperationMapper.save(logVO);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirm(List<String> ids) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<BmsShipBillFeeDetailModel> detailModels = feeDetailMapper.findByIds(BmsShipBillFeeDetailModel.class, ids.toArray(), null);
        if (ObjectUtil.isEmpty(detailModels)) {
            throw new PluginException("获取费用信息失败");
        }
        for (BmsShipBillFeeDetailModel detailModel : detailModels) {
            if (detailModel.getCheckStatus() == 0 ) {
                throw new PluginException(String.format("费用单[%s]未提交，请先提交！",detailModel.getExpenseName()));
            }
            if (detailModel.getCheckStatus() == 2 ) {
                throw new PluginException(String.format("费用单[%s]已对账确认！",detailModel.getExpenseName()));
            }
            detailModel.setCheckStatus(2);
            detailModel.setUpdateperson(user.getNickname());
            detailModel.setUpdatetime(DateUtil.date());
            feeDetailMapper.update(detailModel);

            // 日志操作
            BmsLogOperationModel logVO = new BmsLogOperationModel();
            logVO.setCreatetime(DateUtil.date());
            logVO.setCreateperson(user.getNickname());
            logVO.setEnterpriseId(user.getEnterpriseId());
            logVO.setEnterpriseName(user.getEnterpriseName());
            logVO.setOrderNo(detailModel.getShipbillNo());
            logVO.setLogMemo("对账确认");
            logVO.setLogType(3);
            logOperationMapper.save(logVO);
        }

    }

    @Override
    public ShipBillFeeDTO detail(String shipbillNo) {
        if (ObjectUtil.isEmpty(shipbillNo)) {
            throw new PluginException("查询条件不能为空");
        }
        ShipBillFeeDTO shipBillDTO = new ShipBillFeeDTO();
        Criteria aClass = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r1 = Restrictions.eq("shipbillNo", shipbillNo);
        aClass.setRestriction(Restrictions.and(r1));
        List<BmsShipBillHeaderModel> models = shipBillHeadMapper.findByCriteria(aClass);
        if (ObjectUtil.isEmpty(models)) {
            throw new PluginException("查询运单信息为空");
        }
        BmsShipBillHeaderModel headerModel = models.get(0);
        BeanUtils.copyProperties(headerModel, shipBillDTO);

        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.SHIPBILL_STATUS, // 运单状态
                BmsConstant.SHIPPER_TYPE, // 运输状态
                BmsConstant.ABNORMAL_STATUS, // 异常状态
                BmsConstant.ORDER_TYPE, // 订单类型
                BmsConstant.CONSIGNEE_TYPE, // 收货方类型
                BmsConstant.ORDER_BUSINESS_TYPE, // 订单业务类型
                BmsConstant.SOURCE, // 来源
                BmsConstant.EXPENSE_STATUS, // 费用状态
                BmsConstant.TEMPERATURE_REQUIREMENT// 温度要求
        });

        shipBillDTO.setOrderTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_TYPE, String.valueOf(headerModel.getOrderType())));
        shipBillDTO.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_BUSINESS_TYPE, String.valueOf(headerModel.getOrderBusinessType())));
        shipBillDTO.setTemperatureRequirementName(ConvertorUtil.getName(dicData, BmsConstant.TEMPERATURE_REQUIREMENT, String.valueOf(headerModel.getTemperatureRequirement())));
        shipBillDTO.setShipperTypeName(ConvertorUtil.getName(dicData, BmsConstant.SHIPPER_TYPE, String.valueOf(headerModel.getShipperType())));
        shipBillDTO.setConsigneeTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONSIGNEE_TYPE, String.valueOf(headerModel.getConsigneeType())));
        shipBillDTO.setDeliveryMethodTypeName(headerModel.getDeliveryMethodType() == 1 ? "配送" : "自提");
        shipBillDTO.setTransportTypeName(headerModel.getTransportType() == 1 ? "整车" : "零担");
        shipBillDTO.setStatusName(ConvertorUtil.getName(dicData, BmsConstant.SHIPBILL_STATUS, String.valueOf(headerModel.getStatus())));
        shipBillDTO.setSourceName(ConvertorUtil.getName(dicData, BmsConstant.SOURCE, String.valueOf(headerModel.getSource())));
        shipBillDTO.setCarrierTypeName(headerModel.getCarrierType() == 1 ? "承运商" : "司机");

        // 运单费用
        Criteria criteria = Criteria.forClass(BmsShipBillFeeDetailModel.class);
        Restriction r2 = Restrictions.eq("shipbillNo", headerModel.getShipbillNo());
        criteria.setRestriction(Restrictions.and(r2));
        List<BmsShipBillFeeDetailModel> detailModels = feeDetailMapper.findByCriteria(criteria);

        List<ShipBillFeeDetail> list = Lists.newArrayList();
        for (BmsShipBillFeeDetailModel detailModel : detailModels) {
            ShipBillFeeDetail detail = new ShipBillFeeDetail();
            BeanUtils.copyProperties(detailModel, detail);
            detail.setExpenseStatusName(ConvertorUtil.getName(dicData, BmsConstant.EXPENSE_STATUS, String.valueOf(detailModel.getExpenseStatus())));
            detail.setBillingSourceName(detailModel.getBillingSource() == 1 ? "价格表生成" : "手工录入");
            detail.setBillingTypeName(detailModel.getBillingType());
            list.add(detail);
        }

        Criteria dCriteria = Criteria.forClass(BmsShipBillDetailModel.class);
        Restriction r3 = Restrictions.eq("shipbillNo", headerModel.getShipbillNo());
        dCriteria.setRestriction(Restrictions.and(r3));
        List<BmsShipBillDetailModel> itemDetail = detailMapper.findByCriteria(dCriteria);

        List<ShipBillDetailDTO> itemList = Lists.newArrayList();
        for (BmsShipBillDetailModel detailModel : itemDetail) {
            ShipBillDetailDTO dto = new ShipBillDetailDTO();
            BeanUtils.copyProperties(detailModel, dto);
            dto.setCargoThermosphereName(ConvertorUtil.getName(dicData, BmsConstant.TEMPERATURE_REQUIREMENT, String.valueOf(detailModel.getCargoThermosphere())));
            itemList.add(dto);
        }
        shipBillDTO.setList(list);
        shipBillDTO.setItemList(itemList);
        return shipBillDTO;
    }
}