package com.maintain.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.maintain.business.domain.*;
import com.maintain.business.domain.vo.ErpGroupVo;
import com.maintain.business.domain.vo.ErpRepairFormDeliveryVo;
import com.maintain.business.mapper.*;
import com.maintain.business.service.IErpMaterialService;
import com.maintain.common.core.domain.entity.SysDept;
import com.maintain.common.enums.PickingState;
import com.maintain.common.enums.RepairFormState;
import com.maintain.common.helper.LoginHelper;
import com.maintain.common.utils.StringUtils;
import com.maintain.common.core.page.TableDataInfo;
import com.maintain.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.maintain.common.utils.redis.RedisUtils;
import com.maintain.system.mapper.SysDeptMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.maintain.business.domain.bo.ErpRepairFormBo;
import com.maintain.business.domain.vo.ErpRepairFormVo;
import com.maintain.business.service.IErpRepairFormService;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 报修单Service业务层处理
 *
 * @author liushuai
 * @date 2025-04-01
 */
@RequiredArgsConstructor
@Service
public class ErpRepairFormServiceImpl implements IErpRepairFormService {

    private final ErpRepairFormMapper baseMapper;
    private final ErpCarMapper carMapper;
    private final ErpVehicleModelMapper vehicleModelMapper;
    private final ErpClientMapper clientMapper;
    private final ErpRepairFormProjectMapper projectMapper;
    private final ErpMaterialPickingMapper materialMapper;
    private final ErpRepairFormDeliveryMapper deliveryMapper;
    private final ErpRepairFormClaimMapper claimMapper;
    private final SysDeptMapper deptMapper;
    private final ErpGroupMapper groupMapper;
    private final ErpMaterialPickingInfoMapper pickingInfoMapper;
    private final ErpMaterialPickingMapper pickingMapper;
    private final IErpMaterialService materialService;

    /**
     * 查询报修单
     */
    @Override
    public ErpRepairFormVo queryById(Long id){
        ErpRepairFormVo repairFormVo = baseMapper.selectVoById(id);
        // 车辆
        repairFormVo.setCar(carMapper.selectVoById(repairFormVo.getCarId()));
        // 车型
        repairFormVo.setVehicleModelVo(vehicleModelMapper.selectVoById(repairFormVo.getVehicleModelId()));
        // 客户
        repairFormVo.setClient(clientMapper.selectVoById(repairFormVo.getClientId()));
        // 维修项目/竣工列表
        LambdaQueryWrapper<ErpRepairFormProject> projectLambdaQueryWrapper = Wrappers.lambdaQuery();
        projectLambdaQueryWrapper.eq(ErpRepairFormProject::getRepairFormId, id);
        repairFormVo.setProjectVoList(projectMapper.selectVoList(projectLambdaQueryWrapper));
        // 材料列表
        LambdaQueryWrapper<ErpMaterialPicking> materialLambdaQueryWrapper = Wrappers.lambdaQuery();
        materialLambdaQueryWrapper.eq(ErpMaterialPicking::getRepairFormId, id);
        repairFormVo.setMaterialVoList(materialMapper.selectVoList(materialLambdaQueryWrapper));
        // 交车信息
        LambdaQueryWrapper<ErpRepairFormDelivery> deliveryLambdaQueryWrapper = Wrappers.lambdaQuery();
        deliveryLambdaQueryWrapper.eq(ErpRepairFormDelivery::getRepairFormId, id);
        repairFormVo.setDeliveryVo(deliveryMapper.selectVoOne(deliveryLambdaQueryWrapper));
        // 理赔列表
        LambdaQueryWrapper<ErpRepairFormClaim> claimLambdaQueryWrapper = Wrappers.lambdaQuery();
        claimLambdaQueryWrapper.eq(ErpRepairFormClaim::getRepairFormId, id);
        repairFormVo.setClaimVoList(claimMapper.selectVoList(claimLambdaQueryWrapper));
        return repairFormVo;
    }

    /**
     * 查询报修单
     *
     * @param id
     */
    @Override
    public ErpRepairFormVo customQueryById(Long id) {
        ErpRepairFormVo repairFormVo = baseMapper.customQueryById(id);
        // 维修项目/竣工列表
        LambdaQueryWrapper<ErpRepairFormProject> projectLambdaQueryWrapper = Wrappers.lambdaQuery();
        projectLambdaQueryWrapper.eq(ErpRepairFormProject::getRepairFormId, id);
        repairFormVo.setProjectVoList(projectMapper.selectVoList(projectLambdaQueryWrapper));
        // 材料列表
        LambdaQueryWrapper<ErpMaterialPicking> materialLambdaQueryWrapper = Wrappers.lambdaQuery();
        materialLambdaQueryWrapper.eq(ErpMaterialPicking::getRepairFormId, id);
        repairFormVo.setMaterialVoList(materialMapper.selectVoList(materialLambdaQueryWrapper));
        // 交车信息
        LambdaQueryWrapper<ErpRepairFormDelivery> deliveryLambdaQueryWrapper = Wrappers.lambdaQuery();
        deliveryLambdaQueryWrapper.eq(ErpRepairFormDelivery::getRepairFormId, id);
        ErpRepairFormDeliveryVo deliveryVo = new ErpRepairFormDeliveryVo();
        ErpRepairFormDeliveryVo formDeliveryVo = deliveryMapper.selectVoOne(deliveryLambdaQueryWrapper);
        if (null != formDeliveryVo) {
            deliveryVo = formDeliveryVo;
        }
        repairFormVo.setDeliveryVo(deliveryVo);
        // 理赔列表
        LambdaQueryWrapper<ErpRepairFormClaim> claimLambdaQueryWrapper = Wrappers.lambdaQuery();
        claimLambdaQueryWrapper.eq(ErpRepairFormClaim::getRepairFormId, id);
        repairFormVo.setClaimVoList(claimMapper.selectVoList(claimLambdaQueryWrapper));
        return repairFormVo;
    }

    /**
     * 查询报修单列表
     */
    @Override
    public TableDataInfo<ErpRepairFormVo> queryPageList(ErpRepairFormBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ErpRepairForm> lqw = buildQueryWrapper(bo);
        Page<ErpRepairFormVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询报修单列表(自定义分页查询)
     *
     * @param bo
     * @param pageQuery
     */
    @Override
    public TableDataInfo<ErpRepairFormVo> customQueryPageList(ErpRepairFormBo bo, PageQuery pageQuery) {
        Page<ErpRepairFormVo> carVoPage = baseMapper.customQueryPageList(pageQuery.build(), this.buildCustomQueryWrapper(bo));
        return TableDataInfo.build(carVoPage);
    }


    /**
     * 查询报修单列表(自定义查询)
     *
     * @param bo
     */
    @Override
    public List<ErpRepairFormVo> customQueryList(ErpRepairFormBo bo) {
        return baseMapper.customQueryList(this.buildCustomQueryWrapper(bo));
    }

    /**
     * 查询报修单列表(自定义分页查询)
     *
     * @param ids
     */
    @Override
    public List<ErpRepairFormVo> customQueryList(List<Long> ids) {
        return baseMapper.customQueryListByIds(ids);
    }

    /**
     * 查询报修单列表
     */
    @Override
    public List<ErpRepairFormVo> queryList(ErpRepairFormBo bo) {
        LambdaQueryWrapper<ErpRepairForm> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<ErpRepairFormVo> queryListByIds(List<Long> ids) {
        return baseMapper.selectVoBatchIds(ids);
    }

    private QueryWrapper<ErpRepairForm> buildCustomQueryWrapper(ErpRepairFormBo bo) {
        List<SysDept> sysDeptList = deptMapper.selectChildrenDeptById(LoginHelper.getDeptId());
        QueryWrapper<ErpRepairForm> query = Wrappers.query();
        query
            .like(StringUtils.isNotBlank(bo.getRepairNumber()), "erf.repair_number", bo.getRepairNumber())
            .like(StringUtils.isNotBlank(bo.getPlateNumber()), "ec.plate_number", bo.getPlateNumber())
            .eq(bo.getState() != null, "erf.state", bo.getState())
            .in(bo.getStateList() != null, "erf.state", bo.getStateList())
            .eq(bo.getSettlementState() != null, "erf.settlement_state", bo.getSettlementState())
            .like(StringUtils.isNotBlank(bo.getClientName()), "ec2.name", bo.getClientName())
            .like(StringUtils.isNotBlank(bo.getContact()), "ec2.contact", bo.getContact())
            .like(StringUtils.isNotBlank(bo.getPhone()), "ec2.phone", bo.getPhone())
            .eq(bo.getClientType() != null, "ec2.type", bo.getClientType())
            .eq(bo.getIsDelivery() != null, "erf.is_delivery", bo.getIsDelivery())
            .between(bo.getStartTime() != null && bo.getEndTime() != null, "erf.create_time", bo.getStartTime(), bo.getEndTime())
            .between(bo.getDeliveryStartTime() != null && bo.getDeliveryEndTime() != null, "erf.delivery_time", bo.getDeliveryStartTime(), bo.getDeliveryEndTime())
            .in(!sysDeptList.isEmpty(), "erf.create_dept_id", sysDeptList.stream().map(SysDept::getDeptId).collect(Collectors.toList()));
        query.orderByDesc("erf.create_time");
        return query;
    }

    private LambdaQueryWrapper<ErpRepairForm> buildQueryWrapper(ErpRepairFormBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ErpRepairForm> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCarId() != null, ErpRepairForm::getCarId, bo.getCarId());
        lqw.eq(bo.getVehicleModelId() != null, ErpRepairForm::getVehicleModelId, bo.getVehicleModelId());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairNumber()), ErpRepairForm::getRepairNumber, bo.getRepairNumber());
        lqw.eq(bo.getRepairType() != null, ErpRepairForm::getRepairType, bo.getRepairType());
        lqw.eq(bo.getIsRebuild() != null, ErpRepairForm::getIsRebuild, bo.getIsRebuild());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairCause()), ErpRepairForm::getRepairCause, bo.getRepairCause());
        lqw.eq(bo.getVehicleKilometers() != null, ErpRepairForm::getVehicleKilometers, bo.getVehicleKilometers());
        lqw.eq(bo.getIsOldPart() != null, ErpRepairForm::getIsOldPart, bo.getIsOldPart());
        lqw.eq(bo.getIsByoPart() != null, ErpRepairForm::getIsByoPart, bo.getIsByoPart());
        lqw.eq(StringUtils.isNotBlank(bo.getByoPartRemark()), ErpRepairForm::getByoPartRemark, bo.getByoPartRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getByoPartUrl()), ErpRepairForm::getByoPartUrl, bo.getByoPartUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getDashboardUrl()), ErpRepairForm::getDashboardUrl, bo.getDashboardUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getBodyConditionUrl()), ErpRepairForm::getBodyConditionUrl, bo.getBodyConditionUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getTrailerDocumentNumber()), ErpRepairForm::getTrailerDocumentNumber, bo.getTrailerDocumentNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getTrailerCompany()), ErpRepairForm::getTrailerCompany, bo.getTrailerCompany());
        lqw.eq(StringUtils.isNotBlank(bo.getTrailerPlateNumber()), ErpRepairForm::getTrailerPlateNumber, bo.getTrailerPlateNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getTrailerDriver()), ErpRepairForm::getTrailerDriver, bo.getTrailerDriver());
        lqw.eq(StringUtils.isNotBlank(bo.getTrailerPhone()), ErpRepairForm::getTrailerPhone, bo.getTrailerPhone());
        lqw.eq(bo.getTrailerVehicleKilometers() != null, ErpRepairForm::getTrailerVehicleKilometers, bo.getTrailerVehicleKilometers());
        lqw.eq(bo.getTrailerMoney() != null, ErpRepairForm::getTrailerMoney, bo.getTrailerMoney());
        lqw.eq(bo.getTrailerStartTime() != null, ErpRepairForm::getTrailerStartTime, bo.getTrailerStartTime());
        lqw.eq(bo.getTrailerEndTime() != null, ErpRepairForm::getTrailerEndTime, bo.getTrailerEndTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTrailerRemark()), ErpRepairForm::getTrailerRemark, bo.getTrailerRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getRescueLocation()), ErpRepairForm::getRescueLocation, bo.getRescueLocation());
        lqw.eq(StringUtils.isNotBlank(bo.getDestinationLocation()), ErpRepairForm::getDestinationLocation, bo.getDestinationLocation());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairerCompany()), ErpRepairForm::getRepairerCompany, bo.getRepairerCompany());
        lqw.eq(bo.getRepairerDeptId() != null, ErpRepairForm::getRepairerDeptId, bo.getRepairerDeptId());
        lqw.eq(bo.getRepairerGroupId() != null, ErpRepairForm::getRepairerGroupId, bo.getRepairerGroupId());
        lqw.eq(StringUtils.isNotBlank(bo.getMalfunctionItem()), ErpRepairForm::getMalfunctionItem, bo.getMalfunctionItem());
        lqw.eq(StringUtils.isNotBlank(bo.getExamineItem()), ErpRepairForm::getExamineItem, bo.getExamineItem());
        lqw.eq(bo.getState() != null, ErpRepairForm::getState, bo.getState());
        lqw.eq(bo.getMaintainEndTime() != null, ErpRepairForm::getMaintainEndTime, bo.getMaintainEndTime());
        lqw.eq(bo.getIsDelivery() != null, ErpRepairForm::getIsDelivery, bo.getIsDelivery());
        lqw.eq(bo.getDeliveryTime() != null, ErpRepairForm::getDeliveryTime, bo.getDeliveryTime());
        lqw.eq(bo.getSettlementTime() != null, ErpRepairForm::getSettlementTime, bo.getSettlementTime());
        return lqw;
    }

    /**
     * 新增报修单
     */
    @Override
    public Boolean insertByBo(ErpRepairFormBo bo) {
        ErpRepairForm add = BeanUtil.toBean(bo, ErpRepairForm.class);
        add.setRepairNumber(RedisUtils.generateNextNumber("BX"));
        validEntityBeforeSave(add);
        add.setCreateDeptId(LoginHelper.getDeptId());
        SysDept sysDept = deptMapper.selectVoById(bo.getRepairerDeptId());
        add.setRepairerDeptName(sysDept.getDeptName());
        ErpGroupVo groupVo = groupMapper.selectVoById(bo.getRepairerGroupId());
        add.setRepairerGroupName(groupVo.getName());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改报修单
     */
    @Override
    public Boolean updateByBo(ErpRepairFormBo bo) {
        ErpRepairForm update = BeanUtil.toBean(bo, ErpRepairForm.class);
        validEntityBeforeSave(update);
        SysDept sysDept = deptMapper.selectVoById(bo.getRepairerDeptId());
        update.setRepairerDeptName(sysDept.getDeptName());
        ErpGroupVo groupVo = groupMapper.selectVoById(bo.getRepairerGroupId());
        update.setRepairerGroupName(groupVo.getName());
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 作废报修单
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean abolishByBo(Long id) {
        ErpRepairForm repairForm = baseMapper.selectById(id);
        repairForm.setState(RepairFormState.THREE.getCode());
        boolean flag = baseMapper.updateById(repairForm) > 0;
        if (flag) {
            // 将已完成的出库明细库存还原
            LambdaQueryWrapper<ErpMaterialPickingInfo> pickingInfoLambdaQueryWrapper = Wrappers.lambdaQuery();
            pickingInfoLambdaQueryWrapper.eq(ErpMaterialPickingInfo::getRepairFormId, repairForm.getId()).eq(ErpMaterialPickingInfo::getState, PickingState.TWO.getCode());
            List<ErpMaterialPickingInfo> pickingInfoList = pickingInfoMapper.selectList(pickingInfoLambdaQueryWrapper);
            for (ErpMaterialPickingInfo pickingInfo : pickingInfoList) {
                materialService.modifyMaterialInventory(pickingInfo.getMaterialId(), pickingInfo.getCollectNumber(), true);
            }
            // 将出库单以及出库明细所有状态全部更新为已退料
            LambdaUpdateWrapper<ErpMaterialPicking> pickingLambdaUpdateWrapper = Wrappers.lambdaUpdate();
            pickingLambdaUpdateWrapper.eq(ErpMaterialPicking::getRepairFormId, repairForm.getId());
            pickingLambdaUpdateWrapper.set(ErpMaterialPicking::getState, PickingState.THREE.getCode());
            pickingMapper.update(pickingLambdaUpdateWrapper);
            LambdaUpdateWrapper<ErpMaterialPickingInfo> pickingInfoLambdaUpdateWrapper = Wrappers.lambdaUpdate();
            pickingInfoLambdaUpdateWrapper.eq(ErpMaterialPickingInfo::getRepairFormId, repairForm.getId());
            pickingInfoLambdaUpdateWrapper.set(ErpMaterialPickingInfo::getState, PickingState.THREE.getCode());
            pickingInfoMapper.update(pickingInfoLambdaUpdateWrapper);
        }
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ErpRepairForm entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除报修单
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
