package com.ningdatech.carapi.archives.manage;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService;
import com.ningdatech.carapi.common.constant.CommonConstant;
import com.ningdatech.carapi.common.constant.MissCertEnum;
import com.ningdatech.carapi.common.constant.ViolationTypeEnum;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.qrcode.entity.NdVehicleGetOn;
import com.ningdatech.carapi.qrcode.model.vo.GetOnVehicleVO;
import com.ningdatech.carapi.qrcode.service.VehicleGetOnService;
import com.ningdatech.carapi.safe.entity.NdVehicleViolation;
import com.ningdatech.carapi.safe.manage.VehicleAccidentManage;
import com.ningdatech.carapi.safe.model.dto.AccidentPageQuery;
import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentAnalysisVO;
import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentDeadVO;
import com.ningdatech.carapi.safe.model.vo.NdVehicleAccidentVO;
import com.ningdatech.carapi.safe.model.vo.NdVehicleViolationVO;
import com.ningdatech.carapi.safe.service.INdVehicleAccidentAnalysisService;
import com.ningdatech.carapi.safe.service.INdVehicleAccidentDeadService;
import com.ningdatech.carapi.safe.service.INdVehicleViolationService;
import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO;
import com.ningdatech.carapi.sys.manage.OperatorManage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;

/**
 * @Classname ArchivesManage
 * @Description
 * @Date 2022/11/1 14:33
 * @Created by PoffyZhang
 */
@Component
@RequiredArgsConstructor
public class ArchivesManage {

    private final IVehicleBaseInfoService vehicleBaseInfoService;
    private final INdVehicleViolationService vehicleViolationService;
    private final INdVehicleAccidentDeadService vehicleAccidentDeadService;
    private final INdVehicleAccidentAnalysisService vehicleAccidentAnalysisService;

    private final VehicleGetOnService vehicleGetOnService;
    private final OperatorManage operatorManage;

    private final VehicleAccidentManage vehicleAccidentManage;


    /**
     * 根据车牌号查询运营商
     * @param carPlate
     * @return
     */
    public OperatorQueryDTO getOperatorDetails(String carPlate) {
        LambdaQueryWrapper<NdVehicleBaseInfo> wrapper = Wrappers.lambdaQuery(NdVehicleBaseInfo.class);
        wrapper.eq(NdVehicleBaseInfo::getCarPlate,carPlate);
        List<NdVehicleBaseInfo> vehicles = vehicleBaseInfoService.list(wrapper);
        if(CollUtil.isEmpty(vehicles)){
            return null;
        }
        return operatorManage.getDetails(vehicles.get(0).getOperatorId());
    }

    /**
     * 违章信息
     * @param carPlate violationType
     * @return
     */
    public List<NdVehicleViolationVO> getViolation(String carPlate, Integer violationType) {

        LambdaQueryWrapper<NdVehicleViolation> wrapper = Wrappers.lambdaQuery(NdVehicleViolation.class);
        ArchivesManage context = (ArchivesManage) AopContext.currentProxy();
        context.buildQuery(wrapper, carPlate,violationType);
        List<NdVehicleViolation> list = vehicleViolationService.list(wrapper);

        if(CollUtil.isEmpty(list)){
            return Collections.emptyList();
        }

        return list.stream().map(w -> {
            NdVehicleViolationVO vo = BeanUtil.copyProperties(w, NdVehicleViolationVO.class);
            if(Objects.nonNull(vo.getViolationType())){
                vo.setViolationTypeName(ViolationTypeEnum.getDescByCode(vo.getViolationType()));
            }
            if(Objects.nonNull(vo.getMissingCertificateType())){
                vo.setMissingCertificateTypeName(MissCertEnum.getDescByCode(vo.getMissingCertificateType()));
            }
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildQuery(LambdaQueryWrapper<NdVehicleViolation> wrapper, String carPlate, Integer violationType) {
        wrapper.eq(NdVehicleViolation::getCarPlate,carPlate);
        wrapper.eq(NdVehicleViolation::getViolationType, violationType);
    }

    /**
     * 车辆事故
     * @param carPlate
     * @return
     */
    public List<NdVehicleAccidentVO> getAccidentVehicle(String carPlate) {
        AccidentPageQuery param = new AccidentPageQuery();
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        param.setCarPlate(carPlate);
        PageVo<NdVehicleAccidentVO> page = vehicleAccidentManage.queryVehicleAccident(param);
        if(0L == page.getTotal()){
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(), w -> {
            NdVehicleAccidentVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }
    public List<NdVehicleAccidentVO> getAccidentVehicleOpen(String carPlate) {
        AccidentPageQuery param = new AccidentPageQuery();
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        param.setCarPlate(carPlate);
        PageVo<NdVehicleAccidentVO> page = vehicleAccidentManage.queryVehicleAccidentOpen(param);
        if(0L == page.getTotal()){
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(), w -> {
            NdVehicleAccidentVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }

    public List<NdVehicleAccidentDeadVO> getAccidentDead(String carPlate) {
        AccidentPageQuery param = new AccidentPageQuery();
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        param.setCarPlate(carPlate);
        PageVo<NdVehicleAccidentDeadVO> page = vehicleAccidentManage.queryDead(param);
        if(0L == page.getTotal()){
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(), w -> {
            NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentDeadVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }
    public List<NdVehicleAccidentDeadVO> getAccidentDeadOpen(String carPlate) {
        AccidentPageQuery param = new AccidentPageQuery();
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        param.setCarPlate(carPlate);
        PageVo<NdVehicleAccidentDeadVO> page = vehicleAccidentManage.queryDeadOpen(param);
        if(0L == page.getTotal()){
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(), w -> {
            NdVehicleAccidentDeadVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentDeadVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }

    public List<NdVehicleAccidentAnalysisVO> getAccidentAnalysis(String carPlate) {
        AccidentPageQuery param = new AccidentPageQuery();
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        param.setCarPlate(carPlate);
        PageVo<NdVehicleAccidentAnalysisVO> page = vehicleAccidentManage.queryAccidentAnalysis(param);
        if(0L == page.getTotal()){
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(), w -> {
            NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentAnalysisVO.class);
            CodeUtil.searchRegionName(vo);
            return vo;
        });
    }

    public List<NdVehicleAccidentAnalysisVO> getAccidentAnalysisOpen(String carPlate) {
        AccidentPageQuery param = new AccidentPageQuery();
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        param.setCarPlate(carPlate);
        PageVo<NdVehicleAccidentAnalysisVO> page = vehicleAccidentManage.queryAccidentAnalysis(param);
        if(0L == page.getTotal()){
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(), w -> {
            NdVehicleAccidentAnalysisVO vo = BeanUtil.copyProperties(w, NdVehicleAccidentAnalysisVO.class);
            CodeUtil.searchRegionName(vo);
            return vo;
        });
    }

    public List<GetOnVehicleVO> getOnCar(String carPlate) {
        LambdaQueryWrapper<NdVehicleGetOn> wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class);
        ArchivesManage context = (ArchivesManage) AopContext.currentProxy();
        context.buildGetOnCarQuery(wrapper, carPlate);
        List<NdVehicleGetOn> list = vehicleGetOnService.list(wrapper);
        if (CollUtil.isEmpty(list)){
            return Collections.emptyList();
        }
        return CollUtils.convert(list, w -> {
            GetOnVehicleVO vo = BeanUtil.copyProperties(w, GetOnVehicleVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildGetOnCarQuery(LambdaQueryWrapper<NdVehicleGetOn> wrapper, String carPlate) {
        wrapper.eq(NdVehicleGetOn::getCarPlate,carPlate);
    }

    public List<GetOnVehicleVO> getOnCarDriver(String driverId) {
        LambdaQueryWrapper<NdVehicleGetOn> wrapper = Wrappers.lambdaQuery(NdVehicleGetOn.class);
        ArchivesManage context = (ArchivesManage) AopContext.currentProxy();
        context.buildGetOnQuery(wrapper, Long.valueOf(driverId));
        List<NdVehicleGetOn> list = vehicleGetOnService.list(wrapper);
        if (CollUtil.isEmpty(list)){
            return Collections.emptyList();
        }
        return CollUtils.convert(list, w -> {
            GetOnVehicleVO vo = BeanUtil.copyProperties(w, GetOnVehicleVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildGetOnQuery(LambdaQueryWrapper<NdVehicleGetOn> wrapper, Long driverId) {
        wrapper.eq(NdVehicleGetOn::getDriverId,driverId);
    }
}
