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

import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
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.*;
import com.prolog.rdc.tms.model.dto.SettlementOrderDTO;
import com.prolog.rdc.tms.model.dto.ShipBillFeeDetail;
import com.prolog.rdc.tms.model.dto.ShipBillFeeDetailDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.vo.PayAmountQueryVO;
import com.prolog.rdc.tms.service.PayAmountService;
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 java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class PayAmountServiceImpl implements PayAmountService {

    @Autowired
    private BmsShipbillSettlementMapper settlementMapper;
    @Autowired
    private BmsShipbillSettlementDetailMapper settlementDetailMapper;
    @Autowired
    private BmsLogOperationMapper logOperationMapper;
    @Autowired
    private ConvertorUtil convertorUtil;
    @Autowired
    private ExpenseManagementMapper managementMapper;
    @Autowired
    private ExpenseAccountMapper expenseAccountMapper;
    @Autowired
    private LogisticsContractMapper logisticsContractMapper;

    @Override
    public Page<SettlementOrderDTO> findList(PayAmountQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        List<SettlementOrderDTO> dtos = Lists.newArrayList();
        List<String> depts = user.getDepts();
        if (ObjectUtil.isEmpty(depts)) {
            return PageUtils.getPage(dtos);
        }
        Criteria criteria = Criteria.forClass(BmsShipbillSettlementModel.class);
        Restriction r1 = ObjectUtil.isEmpty(vo.getSettlementNo())?null: Restrictions.like("settlementNo", "%"+vo.getSettlementNo()+"%");
        Restriction r2 = ObjectUtil.isEmpty(vo.getSettlementName())?null:Restrictions.like("settlementName", "%"+vo.getSettlementName()+"%");
        Restriction r3 = ObjectUtil.isEmpty(vo.getSettlementDepartment())?null:Restrictions.like("settlementDepartment", "%"+vo.getSettlementDepartment()+"%");
        Restriction r4 = ObjectUtil.isEmpty(vo.getSettlementCompany())?null:Restrictions.like("settlementCompany", "%"+vo.getSettlementCompany()+"%");
        vo.setStatus(2);
        Restriction r5 = ObjectUtil.isEmpty(vo.getStatus())?null:Restrictions.eq("status", vo.getStatus());
        Restriction r6 =null;
        if (ObjectUtil.isNotEmpty(vo.getCreateStartTime()) && ObjectUtil.isNotEmpty(vo.getCreateEndTime())) {
            r6 = Restrictions.between("createtime", vo.getCreateStartTime()+" 00:00:00", vo.getCreateEndTime()+" 23:59:59");
        }
        // 大于
        if (ObjectUtil.isNotEmpty(vo.getCreateStartTime()) && ObjectUtil.isEmpty(vo.getCreateEndTime())) {
            r6 = Restrictions.gt("createtime", vo.getCreateStartTime()+" 00:00:00");
        }
        // 小于
        if (ObjectUtil.isEmpty(vo.getCreateStartTime()) && ObjectUtil.isNotEmpty(vo.getCreateEndTime())) {
            r6 = Restrictions.le("createtime", vo.getCreateEndTime()+" 23:59:59");
        }
        Restriction r7 =null;
        if (ObjectUtil.isNotEmpty(vo.getUpdateStartTime()) && ObjectUtil.isNotEmpty(vo.getUpdateEndTime())) {
            r7 = Restrictions.between("updatetime", vo.getUpdateStartTime()+" 00:00:00", vo.getUpdateEndTime()+" 23:59:59");
        }
        // 大于
        if (ObjectUtil.isNotEmpty(vo.getUpdateStartTime()) && ObjectUtil.isEmpty(vo.getUpdateEndTime())) {
            r7 = Restrictions.gt("updatetime", vo.getUpdateStartTime()+" 00:00:00");
        }
        // 小于
        if (ObjectUtil.isEmpty(vo.getUpdateStartTime()) && ObjectUtil.isNotEmpty(vo.getUpdateEndTime())) {
            r7 = Restrictions.le("updatetime", vo.getUpdateEndTime()+" 23:59:59");
        }
        Restriction r8 = Restrictions.in("settlementDepartmentId", depts.toArray());
        Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r10 =null;
        Restriction r11 = null;
        Restriction r12 = null;
        Restriction r13 = null;
        if (user.getOwnedAllDataAuthFlag().equals(BmsConstant.USER_DEPARTMENT_AUTH_Y)) {
            r10 = Restrictions.in("settlementDepartmentId", user.getDepts().toArray());
        } else {
            r10 = Restrictions.in("settlementDepartmentId", user.getDepts().toArray());
            r11 = Restrictions.in("settlementCompanyId", user.getConsignors().toArray());
            r12 = Restrictions.in("carrierId", user.getCarriers().toArray());
            r13 = Restrictions.or(r10, r11, r12);
        }
        criteria.setRestriction(Restrictions.and(r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r13));
        criteria.setOrder(Order.newInstance().desc("updatetime").desc("createtime"));
        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<BmsShipbillSettlementModel> list = settlementMapper.findByCriteria(criteria);

        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[] {
                BmsConstant.SETTLEMENT_CYCLE, // 结算周期
                BmsConstant.CLOSE_ACCOUNT_STATUS, // 结算状态
        });
        for (BmsShipbillSettlementModel bmsShipbillSettlementModel : list) {
            SettlementOrderDTO settlementOrderDTO = new SettlementOrderDTO();
            BeanUtils.copyProperties(bmsShipbillSettlementModel,settlementOrderDTO);
            settlementOrderDTO.setSettlementCycleName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_CYCLE, String.valueOf(bmsShipbillSettlementModel.getSettlementCycle())));
            settlementOrderDTO.setStatusName(ConvertorUtil.getName(dicData, BmsConstant.CLOSE_ACCOUNT_STATUS, String.valueOf(bmsShipbillSettlementModel.getStatus())));
            dtos.add(settlementOrderDTO);
        }
        // 分页设置
        Page<SettlementOrderDTO> page = PageUtils.getPage(dtos);
        if (list instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<BmsShipbillSettlementModel> p0 = (com.github.pagehelper.Page<BmsShipbillSettlementModel>) list;
            page.setPageCount(p0.getPages());
            page.setPageNum(p0.getPageNum());
            page.setPageSize(p0.getPageSize());
            page.setTotalCount(p0.getTotal());
            page.setStartRow(p0.getStartRow());
            page.setEndRow(p0.getEndRow());
        }
        return page;
    }

    @Override
    public List<ShipBillFeeDetailDTO> findListForFee(Long id) {
        BmsShipbillSettlementModel settlementModel = settlementMapper.findById(id, BmsShipbillSettlementModel.class);
        if (ObjectUtil.isEmpty(settlementModel)) {
            throw new PluginException("查询结算费用信息为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        // 查询所有的费用单
        Criteria forClass = Criteria.forClass(BmsShipbillSettlementDetailModel.class);
        Restriction r1 = Restrictions.eq("settlementNo", settlementModel.getSettlementNo());
        forClass.setRestriction(Restrictions.and(r1));
        List<BmsShipbillSettlementDetailModel> models = settlementDetailMapper.findByCriteria(forClass);
        if (ObjectUtil.isEmpty(models)) {
            throw new PluginException("查询结算单详情为空");
        }

        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.CHECK_STATUS, // 结算状态
                BmsConstant.SETTLEMENT_STATUS,
                BmsConstant.TEMPERATURE_REQUIREMENT// 温度要求
        });

        List<ShipBillFeeDetailDTO> list = Lists.newArrayList();
        for (BmsShipbillSettlementDetailModel feeDetailModel : models) {
            ShipBillFeeDetailDTO feeDetail = new ShipBillFeeDetailDTO();
            BeanUtils.copyProperties(feeDetailModel,feeDetail);
            feeDetail.setExpenseStatusName(ConvertorUtil.getName(dicData, BmsConstant.EXPENSE_STATUS, String.valueOf(feeDetailModel.getExpenseStatus())));

            Criteria mClass = Criteria.forClass(BmsExpenseManagementModel.class);
            Restriction r7 = Restrictions.eq("status", 1);
            Restriction r8 = Restrictions.eq("expenseName", feeDetailModel.getExpenseName());
            Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
            mClass.setRestriction(Restrictions.and(r7, r8,r9));
            List<BmsExpenseManagementModel> managementModels = managementMapper.findByCriteria(mClass);
            if (ObjectUtil.isEmpty(managementModels)) {
                throw new PluginException("获取费用信息失败");
            }
            BmsExpenseManagementModel managementModel = managementModels.get(0);

            // 支出，收入
            String expenseAccountCode = managementModel.getExpenseAccountCode();
            Criteria aClass = Criteria.forClass(ExpenseAccountModel.class);
            Restriction r11 = Restrictions.eq("expenseCode", expenseAccountCode);
            Restriction r12 = Restrictions.eq("status", 1);
            aClass.setRestriction(Restrictions.and(r11, r12));
            List<ExpenseAccountModel> mapper = expenseAccountMapper.findByCriteria(aClass);
            if (ObjectUtil.isNotEmpty(mapper)) {
                feeDetail.setExpenseTypeName(Objects.equals(mapper.get(0).getExpenseClassify(), 1) ? "收入" : "支出");
            }

            // 查询结算周期
            String costContract = feeDetail.getCostContract();
            Criteria criteria = Criteria.forClass(BmsLogisticsContractModel.class);
            Restriction r2 = Restrictions.eq("contractName", costContract);
            Restriction r3 = Restrictions.eq("status", 1);
            criteria.setRestriction(Restrictions.and(r2,r3));
            List<BmsLogisticsContractModel> contractModels = logisticsContractMapper.findByCriteria(criteria);
            if (ObjectUtil.isNotEmpty(contractModels)) {
                BmsLogisticsContractModel contractModel = contractModels.get(0);
                Integer settlementType = contractModel.getSettlementType();
                feeDetail.setSettlementCycle(settlementType);
            }
            feeDetail.setBillingStatusName(feeDetailModel.getBillingStatus() == 1?"计费成功":"未计费");
            feeDetail.setCostContract(feeDetailModel.getCostContract());
            feeDetail.setCostDate(feeDetailModel.getCostDate());
            feeDetail.setBillingPrice(feeDetailModel.getCostPriceTable());
            feeDetail.setCostFailReason(feeDetailModel.getCostFailReason());

            feeDetail.setBillingSourceName(feeDetailModel.getBillingSource() == 1 ? "价格表生成" : "手工录入");
            feeDetail.setCheckStatusName(ConvertorUtil.getName(dicData, BmsConstant.CHECK_STATUS, String.valueOf(feeDetailModel.getCheckStatus())));
            feeDetail.setExpenseMemo(feeDetailModel.getMemo());
            feeDetail.setOrderTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_TYPE, String.valueOf(feeDetailModel.getOrderType())));
            feeDetail.setOrderBusinessTypeName(ConvertorUtil.getName(dicData, BmsConstant.ORDER_BUSINESS_TYPE, String.valueOf(feeDetailModel.getOrderBusinessType())));
            feeDetail.setTemperatureRequirementName(ConvertorUtil.getName(dicData, BmsConstant.TEMPERATURE_REQUIREMENT, String.valueOf(feeDetailModel.getTemperatureRequirement())));
            feeDetail.setShipperTypeName(ConvertorUtil.getName(dicData, BmsConstant.SHIPPER_TYPE, String.valueOf(feeDetailModel.getShipperType())));
            feeDetail.setConsigneeTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONSIGNEE_TYPE, String.valueOf(feeDetailModel.getConsigneeType())));
            feeDetail.setDeliveryMethodTypeName(feeDetailModel.getDeliveryMethodType() == 1 ? "配送" : "自提");
            feeDetail.setTransportTypeName(feeDetailModel.getTransportType() == 1 ? "整车" : "零担");
            feeDetail.setSourceName(feeDetailModel.getBillingSource().intValue()==1 ? "价格表生成" : "手工录入");
            feeDetail.setSettlementStatusName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_STATUS, String.valueOf(feeDetailModel.getSettlementStatus())));
            feeDetail.setCarrierTypeName(feeDetailModel.getCarrierType() == 1 ? "承运商" : "司机");

            if (feeDetail.getCarrierType().intValue() == 2) {
                feeDetail.setCarrierName(feeDetail.getDriverName());
            }

            list.add(feeDetail);
        }
        return list;
    }

    @Override
    public List<BmsLogOperationModel> findListForLog(Long id) {
        BmsShipbillSettlementModel settlementModel = settlementMapper.findById(id, BmsShipbillSettlementModel.class);
        if (ObjectUtil.isEmpty(settlementModel)) {
            throw new PluginException("查询结算费用信息为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria lCriteria = Criteria.forClass(BmsLogOperationModel.class);
        Restriction r1 = Restrictions.eq("orderNo", settlementModel.getExpenseNo());
        Restriction r2 = Restrictions.eq("logType", 4);
        Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        lCriteria.setRestriction(Restrictions.and(r1,r2,r3));
        lCriteria.setOrder(Order.newInstance().asc("updatetime"));
        return logOperationMapper.findByCriteria(lCriteria);
    }
}