package com.ningdatech.carapi.industry.manage;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper;
import com.ningdatech.carapi.common.constant.CommonConstant;
import com.ningdatech.carapi.common.constant.UserRoleTypeEnum;
import com.ningdatech.carapi.common.constant.VehicleTypeEnum;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.common.util.ExcelDownUtil;
import com.ningdatech.carapi.common.util.ExcelExportStyle;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.industry.entity.VehicleAnnualInspectionReview;
import com.ningdatech.carapi.industry.model.dto.InspectionReviewSaveDTO;
import com.ningdatech.carapi.industry.model.dto.InspectionReviewUpdateDTO;
import com.ningdatech.carapi.industry.model.dto.ReviewPageParamDTO;
import com.ningdatech.carapi.industry.model.dto.VehicleAnnualInspectionExportDTO;
import com.ningdatech.carapi.industry.model.vo.VehicleAnnualInspectionReviewApplicationVO;
import com.ningdatech.carapi.industry.model.vo.VehicleAnnualInspectionReviewVO;
import com.ningdatech.carapi.industry.service.IVehicleAnnualInspectionReviewService;
import com.ningdatech.carapi.sys.entity.dto.OperatorQueryDTO;
import com.ningdatech.carapi.sys.helper.OperatorsCacheHelper;
import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.carapi.user.util.LoginUserUtil;

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

/**
 * @Classname AnnualInspectionReviewManage
 * @Description
 * @Date 2022/11/3 17:57
 * @Created by PoffyZhang
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class AnnualInspectionReviewManage {

    private final IVehicleAnnualInspectionReviewService vehicleAnnualInspectionReviewService;
    private final OperatorsCacheHelper operatorsCacheHelper;
    private final IVehicleBaseInfoService vehicleBaseInfoService;

    public PageVo<VehicleAnnualInspectionReviewVO> infoList(ReviewPageParamDTO param) {
        Page<VehicleAnnualInspectionReview> page = param.page();

        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商ID
            Long operatorId = operatorQueryDTO.getId();
            // 查询出该运营商下所有车辆
            List<NdVehicleBaseInfo> baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                    .eq(NdVehicleBaseInfo::getOperatorId, operatorId));
            List<String> carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList());
            param.setCarPlateList(carPlateList);
        }

        LambdaQueryWrapper<VehicleAnnualInspectionReview> wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class);
        AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy();
        context.search(page,wrapper,param);
        if(CollUtil.isEmpty(page.getRecords())){
            return PageVo.of(Collections.emptyList(), page.getTotal());
        }
        List<VehicleAnnualInspectionReviewVO> data = page.getRecords().stream().map(w -> convert(w)).collect(Collectors.toList());
        return PageVo.of(data, page.getTotal());
    }

    public VehicleAnnualInspectionReviewVO details(Long id) {

        LambdaQueryWrapper<VehicleAnnualInspectionReview> wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class);
        AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy();
        context.buildQuery(wrapper, id);
        VehicleAnnualInspectionReview record = vehicleAnnualInspectionReviewService.getOne(wrapper);
        if (Objects.isNull(record)){
            return null;
        }

        //VehicleAnnualInspectionReview record = vehicleAnnualInspectionReviewService.getById(id);
        return convert(record);
    }
    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildQuery(LambdaQueryWrapper<VehicleAnnualInspectionReview> wrapper, Long id) {
        wrapper.eq(VehicleAnnualInspectionReview::getId,id);
    }

    public PageVo<VehicleAnnualInspectionReviewApplicationVO> applicationList(ReviewPageParamDTO param) {
        Page<VehicleAnnualInspectionReview> page = param.page();

        // 按照登录用户，如果是运营商账号登录，删选出该运营商关联的车辆信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long roleId = userDetail.getRoleId();
        if (UserRoleTypeEnum.OPERATOR_ROLE_ID.getId().equals(roleId)) {
            String companyName = userDetail.getCompanyName();
            // 暂时控制运营商名称和运营商所在企业名称相同
            OperatorQueryDTO operatorQueryDTO = operatorsCacheHelper.getByName(companyName);
            // 获取运营商ID
            Long operatorId = operatorQueryDTO.getId();
            // 查询出该运营商下所有车辆
            List<NdVehicleBaseInfo> baseInfoList = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                    .eq(NdVehicleBaseInfo::getOperatorId, operatorId));
            List<String> carPlateList = baseInfoList.stream().map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList());
            param.setCarPlateList(carPlateList);
        }

        LambdaQueryWrapper<VehicleAnnualInspectionReview> wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class);
        AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy();
        context.search(page,wrapper,param);
        if(CollUtil.isEmpty(page.getRecords())){
            return PageVo.of(Collections.emptyList(), page.getTotal());
        }
        List<VehicleAnnualInspectionReviewApplicationVO> data = page.getRecords().stream().map(w -> convertApplication(w)).collect(Collectors.toList());
        return PageVo.of(data, page.getTotal());
    }


    /**
     * 查询
     * @param page
     * @param param
     */
    @LambdaDataScope(wrapperIndex = 1)
    @BuildChildrenRegionWrapper(wrapperIndex = 1,entityIndex = 2)
    public void search(Page<VehicleAnnualInspectionReview> page, LambdaQueryWrapper<VehicleAnnualInspectionReview> wrapper,ReviewPageParamDTO param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), VehicleAnnualInspectionReview::getCompanyName, param.getCompanyName())
                .like(StringUtils.isNotBlank(param.getCarPlate()), VehicleAnnualInspectionReview::getCarPlate, param.getCarPlate())
                .eq(Objects.nonNull(param.getVehicleType()), VehicleAnnualInspectionReview::getVehicleType, param.getVehicleType())
                .eq(StringUtils.isNoneBlank(param.getInspectionRecords()), VehicleAnnualInspectionReview::getInspectionRecords, param.getInspectionRecords())
                .in(CollUtil.isNotEmpty(param.getCarPlateList()),VehicleAnnualInspectionReview::getCarPlate,param.getCarPlateList())
                .orderBy(Boolean.TRUE,Boolean.FALSE, VehicleAnnualInspectionReview::getUpdateOn);
        vehicleAnnualInspectionReviewService.page(page, wrapper);
    }

    private VehicleAnnualInspectionReviewVO convert(VehicleAnnualInspectionReview review) {
        if(Objects.isNull(review)){
            return null;
        }
        VehicleAnnualInspectionReviewVO vo = BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewVO.class);
        CodeUtil.searchCompanyNameAndRegionName(vo);
        return vo;
    }

    private VehicleAnnualInspectionReviewApplicationVO convertApplication(VehicleAnnualInspectionReview review) {
        VehicleAnnualInspectionReviewApplicationVO vo = BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewApplicationVO.class);
        CodeUtil.searchCompanyNameAndRegionName(vo);
        vo.setStatus("首次申请");
        vo.setOperation("无");
        return vo;
    }


    public VehicleAnnualInspectionReviewVO save(InspectionReviewSaveDTO data, Long userId) {
        VehicleAnnualInspectionReview review = BeanUtil.copyProperties(data, VehicleAnnualInspectionReview.class);
        review.setRegionId(LoginUserUtil.loginUserDetail().getRegionId());
        CodeUtil.searchCompanyNameAndRegionName(review);
        if(Objects.nonNull(data.getVehicleType())){
            Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(vehicleTypeName ->
                    review.setVehicleTypeName(vehicleTypeName));
        }
        review.setCreateBy(userId);
        review.setUpdateBy(userId);
        vehicleAnnualInspectionReviewService.save(review);
        return BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewVO.class);
    }

    public VehicleAnnualInspectionReviewVO modify(InspectionReviewUpdateDTO data, Long userId) {
        VehicleAnnualInspectionReview review = BeanUtil.copyProperties(data, VehicleAnnualInspectionReview.class);
        CodeUtil.searchCompanyNameAndRegionName(review);
        if(Objects.nonNull(data.getVehicleType())){
            Optional.ofNullable(VehicleTypeEnum.getDescByCode(data.getVehicleType())).ifPresent(vehicleTypeName ->
                    review.setVehicleTypeName(vehicleTypeName));
        }
        review.setUpdateBy(userId);
        vehicleAnnualInspectionReviewService.updateById(review);
        return BeanUtil.copyProperties(review, VehicleAnnualInspectionReviewVO.class);
    }

    public Boolean remove(Long id, Long userId) {

        LambdaQueryWrapper<VehicleAnnualInspectionReview> wrapper = Wrappers.lambdaQuery(VehicleAnnualInspectionReview.class);
        AnnualInspectionReviewManage context = (AnnualInspectionReviewManage) AopContext.currentProxy();
        context.buildQuery(wrapper, id);
        VehicleAnnualInspectionReview record = vehicleAnnualInspectionReviewService.getOne(wrapper);
        if (Objects.isNull(record)){
            throw new BizException("无法撤销!");
        }

        vehicleAnnualInspectionReviewService.removeById(id);
        return Boolean.TRUE;
    }

    public void infoListExport(HttpServletResponse response, ReviewPageParamDTO param) {
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        PageVo<VehicleAnnualInspectionReviewVO> page = infoList(param);
        List<VehicleAnnualInspectionExportDTO> collect = page.getRecords().stream().map(r -> {
            VehicleAnnualInspectionExportDTO exportDTO = new VehicleAnnualInspectionExportDTO();
            BeanUtils.copyProperties(r, exportDTO);
            return exportDTO;
        }).collect(Collectors.toList());
        String fileName = "车辆年检年审记录列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), VehicleAnnualInspectionExportDTO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
