package com.ningdatech.carapi.company.service.impl;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
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.context.ApplicationContext;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.exception.code.ExceptionCode;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.carapi.analysis.common.DangerLevelEnum;
import com.ningdatech.carapi.analysis.entity.WarnAnalysisCompany;
import com.ningdatech.carapi.analysis.service.IWarnAnalysisCompanyService;
import com.ningdatech.carapi.archives.enums.AuditStateEnum;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper;
import com.ningdatech.carapi.common.constant.CommonConstant;
import com.ningdatech.carapi.common.constant.EducationEnum;
import com.ningdatech.carapi.common.constant.UserRoleTypeEnum;
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.company.entity.CompanyBasicCredit;
import com.ningdatech.carapi.company.entity.CompanyEmployees;
import com.ningdatech.carapi.company.entity.CompanyVehicleNotGetOn;
import com.ningdatech.carapi.company.entity.NdCompanyCreditLevel;
import com.ningdatech.carapi.company.entity.dto.*;
import com.ningdatech.carapi.company.entity.vo.CompanyEmployeesVO;
import com.ningdatech.carapi.company.enumeration.CompanyCreditLevelEnum;
import com.ningdatech.carapi.company.enumeration.CompanyTypeEnum;
import com.ningdatech.carapi.company.enumeration.ProductCompanyType;
import com.ningdatech.carapi.company.service.*;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.driver.constant.UserCanLoginEnum;
import com.ningdatech.carapi.driver.constants.DriverConstant;
import com.ningdatech.carapi.open.model.vo.CompanySecurityInfoVO;
import com.ningdatech.carapi.scheduler.enums.DataTypeEnum;
import com.ningdatech.carapi.scheduler.enums.OperatorTypeEnum;
import com.ningdatech.carapi.sys.entity.*;
import com.ningdatech.carapi.sys.entity.dto.CompanyPageQuery;
import com.ningdatech.carapi.sys.entity.dto.CompanySaveDTO;
import com.ningdatech.carapi.sys.entity.vo.CompanyVO;
import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import com.ningdatech.carapi.sys.manage.CompanyManage;
import com.ningdatech.carapi.sys.service.*;
import com.ningdatech.carapi.user.entity.NdUserAuth;
import com.ningdatech.carapi.user.entity.NdUserInfo;
import com.ningdatech.carapi.user.security.auth.constant.AuthTypeEnum;
import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.carapi.user.service.INdUserAuthService;
import com.ningdatech.carapi.user.service.INdUserInfoService;
import com.ningdatech.carapi.user.util.LoginUserUtil;

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

/**
 * @description:
 * @author: liushuai
 * @date: 2022/10/26 08:50
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ICompanyArchivesServiceImpl implements ICompanyArchivesService {
    private final CompanyManage companyManage;
    private final CompanyService companyService;
    private final ICompanyBasicCreditService iCompanyBasicCreditService;
    private final IRegionService iRegionService;
    private final ICompanyEmployeesService iCompanyEmployeesService;
    private final CompanyTypeService companyTypeService;
    private final CompanyTypeRelatedService companyTypeRelatedService;
    private final ApplicationContext applicationContext;
    private final ICompanyVehicleNotGetOnService companyVehicleNotGetOnService;

    private final INdCompanyCreditLevelService companyCreditLevelService;
    private final IWarnAnalysisCompanyService warnAnalysisCompanyService;
    private final RegionsCacheHelper regionCacheHelper;
    private final CompaniesCacheHelper companiesCacheHelper;
    private final INdUserInfoService userInfoService;
    private final PasswordEncoder passwordEncoder;
    private final INdUserAuthService ndUserAuthService;
    private final UserRoleService userRoleService;

    @Override
    public PageVo<ResCompanyArchivesDTO> getCompanyList(CompanyListParamDTO param) {
        CompanyPageQuery companyPageQuery = new CompanyPageQuery();

        companyPageQuery.setCompanyTypeList(param.getCompanyTypeList());
        companyPageQuery.setCompanyType(param.getCompanyType());
        companyPageQuery.setProductCompanyType(param.getProductCompanyType());
        companyPageQuery.setName(param.getCompanyName());

        companyPageQuery.setRegionId(param.getRegionId());
        companyPageQuery.setPageSize(param.getPageSize());
        companyPageQuery.setPageNumber(param.getPageNumber());
        PageVo<CompanyVO> pageVo = companyManage.queryList(companyPageQuery);
        if (pageVo.getTotal() != null && 0L != pageVo.getTotal()) {
            List<ResCompanyArchivesDTO> res = pageVo.getRecords().stream().map(w -> {
                ResCompanyArchivesDTO dto = new ResCompanyArchivesDTO();
                BeanUtil.copyProperties(w, dto);
                dto.setCarCompanyType(w.getCompanyTypeName());
                return dto;
            }).collect(Collectors.toList());
            return PageVo.of(res, pageVo.getTotal());
        }
        return PageVo.empty();
    }

    @Override
    public ResCompanyArchivesDetailsDTO getCompanyDetail(Long companyId) {
        ResCompanyArchivesDetailsDTO companyArchivesDTO = new ResCompanyArchivesDetailsDTO();
        // 获取企业信息
        LambdaQueryWrapper<Company> wrapper = Wrappers.lambdaQuery(Company.class);
        ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl) AopContext.currentProxy();
        context.buildQuery(wrapper, companyId);
        Company company = companyService.getOne(wrapper);
        if (Objects.isNull(company)) {
            throw new BizException("企业不存在");
        }
        //Company company = companyService.getById(companyId);

        BeanUtil.copyProperties(company, companyArchivesDTO);
        // 对手机号进行脱敏处理
        String contactPhone = company.getContactPhone();
        String legalPersonPhone = company.getLegalPersonPhone();
        String encryptContactPhone = DesensitizedUtil.mobilePhone(contactPhone);
        String encryptLegalPersonPhone = DesensitizedUtil.mobilePhone(legalPersonPhone);
        companyArchivesDTO.setContactPhone(encryptContactPhone);
        companyArchivesDTO.setLegalPersonPhone(encryptLegalPersonPhone);
        companyArchivesDTO.setCompanyTypeName(CompanyTypeEnum.getDescByCode(company.getCompanyType()));
        // 获取基础信息
        CompanyBasicCredit companyBasicCredit =
            iCompanyBasicCreditService.getOne(new QueryWrapper<CompanyBasicCredit>().eq("company_id", companyId));
        BeanUtil.copyProperties(companyBasicCredit, companyArchivesDTO);
        // 获取区域信息
        Region region = iRegionService.getById(company.getRegionId());
        companyArchivesDTO.setRegionCode(region.getRegionCode());
        String regionName = regionCacheHelper.getDisplayName(region.getId());
        companyArchivesDTO.setRegionName(regionName);
        // 查询企业类型
        List<CompanyTypeRelated> companyTypeRelateds = companyTypeRelatedService
            .list(Wrappers.lambdaQuery(CompanyTypeRelated.class).eq(CompanyTypeRelated::getCompanyId, companyId));
        if (CollUtil.isNotEmpty(companyTypeRelateds)) {
            companyArchivesDTO.setCarCompanyType(companyTypeRelateds.stream()
                .map(c -> String.valueOf(c.getCompanyTypeId())).collect(Collectors.joining(StrPool.COMMA)));
            companyArchivesDTO.setCarCompanyTypeName(companyTypeRelateds.stream().map(r -> {
                Long companyTypeId = r.getCompanyTypeId();
                CompanyType companyType = companyTypeService.getById(companyTypeId);
                return Objects.nonNull(companyType) ? companyType.getName() : StringUtils.EMPTY;
            }).filter(StringUtils::isNotBlank).collect(Collectors.joining(StrPool.COMMA)));
        }
        return companyArchivesDTO;
    }
    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION)
    public void buildQuery(LambdaQueryWrapper<Company> wrapper, Long companyId) {
        wrapper.eq(Company::getId,companyId);
    }

    @Override
    public List<CompanyEmployeesVO> getCompanyEmployees(Long companyId) {
        List<CompanyEmployees> employeesList = iCompanyEmployeesService.list(new QueryWrapper<CompanyEmployees>().eq("company_id", companyId));
        return employeesList.stream().map(e -> {
            CompanyEmployeesVO vo = new CompanyEmployeesVO();
            BeanUtils.copyProperties(e, vo);

            // 对手机号和身份证号进行脱敏处理
            String mobile = e.getMobile();
            String idCard = e.getCardNum();
            String encryptMobile = DesensitizedUtil.mobilePhone(mobile);
            String encryptIdCard = DesensitizedUtil.idCardNum(idCard, DriverConstant.ID_CARD_DESENSITIZED_FRONT, DriverConstant.ID_CARD_DESENSITIZED_END);
            vo.setMobile(encryptMobile);
            vo.setCardNum(encryptIdCard);

            vo.setEducationName(EducationEnum.getDescByCode(vo.getEducation()));
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public void updateCompanyInfo(ReqCompanyArchivesDetailsDTO reqCompanyArchivesDetailsDTO) {
        Company company = reqCompanyArchivesDetailsDTO.getCompany();
        // 更新企业信息
        Company companyCache = companyService.getById(company.getId());
        BeanUtil.copyProperties(company, companyCache);
        List<Long> enterpriseTypes = reqCompanyArchivesDetailsDTO.getEnterpriseTypes();
        if (CollUtil.isNotEmpty(enterpriseTypes)) {
            // 先删除原来关联的信息，再保存
            companyTypeRelatedService.remove(Wrappers.lambdaQuery(CompanyTypeRelated.class)
                .eq(CompanyTypeRelated::getCompanyId, companyCache.getId()));
            for (Long enterpriseType : enterpriseTypes) {
                CompanyTypeRelated companyTypeRelated = new CompanyTypeRelated();
                companyTypeRelated.setCompanyId(companyCache.getId());
                companyTypeRelated.setCompanyTypeId(enterpriseType);
                companyTypeRelatedService.save(companyTypeRelated);
            }
        }
        companyService.updateById(companyCache);
        CompanyBasicCredit companyBasicCredit = reqCompanyArchivesDetailsDTO.getCompanyBasicCredit();
        // 更新企业基础信息
        if (companyBasicCredit != null) {
            CompanyBasicCredit companyBasicCreditCache = iCompanyBasicCreditService
                .getOne(new QueryWrapper<CompanyBasicCredit>().eq("company_id", company.getId()));
            BeanUtil.copyProperties(companyBasicCredit, companyCache);
            iCompanyBasicCreditService.updateById(companyBasicCreditCache);
        }
        // 更新企业员工信息
        List<CompanyEmployees> companyEmployeesList = reqCompanyArchivesDetailsDTO.getCompanyEmployeesList();
        if (CollectionUtil.isNotEmpty(companyEmployeesList)) {
            // 要先需不需要删除
            List<CompanyEmployees> oldEmployees =
                iCompanyEmployeesService.list(Wrappers.lambdaQuery(CompanyEmployees.class)
                    .eq(CompanyEmployees::getCompanyId, companyEmployeesList.get(0).getCompanyId()));
            Map<Long, CompanyEmployees> employeesMap = CollUtils.listToMap(oldEmployees, CompanyEmployees::getId);
            for (CompanyEmployees companyEmployee : companyEmployeesList) {
                if (Objects.nonNull(companyEmployee.getId()) && employeesMap.containsKey(companyEmployee.getId())) {
                    oldEmployees.remove(employeesMap.get(companyEmployee.getId()));
                }
                iCompanyEmployeesService.saveOrUpdate(companyEmployee);
            }

            if (CollUtil.isNotEmpty(oldEmployees)) {
                // 说明有要删除的
                for (CompanyEmployees companyEmployee : oldEmployees) {
                    iCompanyEmployeesService.removeById(companyEmployee.getId());
                    log.info("触发删除员工事件 :{}", JSON.toJSONString(companyEmployee));
                }
            }
        }
        // 公司类型
        if (StringUtils.isNotEmpty(company.getCarCompanyType())) {
            companyTypeRelatedService.remove(
                Wrappers.lambdaQuery(CompanyTypeRelated.class).eq(CompanyTypeRelated::getCompanyId, company.getId()));
            String carCompanyType = company.getCarCompanyType();
            for (String enterpriseType : carCompanyType.split(StrPool.COMMA)) {
                CompanyType companyType = companyTypeService.getById(enterpriseType);
                if (Objects.nonNull(companyType)) {
                    companyTypeRelatedService.save(new CompanyTypeRelated(null, company.getId(), companyType.getId()));
                }
            }
        }
    }

    @Override
    public PageVo<ResCompanyEmployeesCountDTO> getCompanyEmployeesList(CompanyListParamDTO param) {
        PageVo<ResCompanyEmployeesCountDTO> page = new PageVo<>();
        CompanyPageQuery companyPageQuery = new CompanyPageQuery();
        companyPageQuery.setRegionId(param.getRegionId());
        companyPageQuery.setName(param.getCompanyName());
        companyPageQuery.setPageNumber(param.getPageNumber());
        companyPageQuery.setPageSize(param.getPageSize());
        PageVo<CompanyVO> pageVo = companyManage.queryList(companyPageQuery);
        if (CollUtil.isEmpty(pageVo.getRecords())) {
            return PageVo.empty();
        }
        List<ResCompanyEmployeesCountDTO> countDtos = iCompanyEmployeesService.countEmployeesByCompanyIds(
            pageVo.getRecords().stream().map(CompanyVO::getId).collect(Collectors.toList()));

        page.setTotal(pageVo.getTotal());
        page.setRecords(countDtos);
        return page;
    }

    @Override
    public PageVo<ResCompanyBasicCreditDTO> getCompanyBasicCreditList(CompanyListParamDTO param) {
        PageVo<ResCompanyBasicCreditDTO> page = new PageVo<>();
        List<ResCompanyBasicCreditDTO> result = new ArrayList<>();
        CompanyPageQuery companyPageQuery = new CompanyPageQuery();
        companyPageQuery.setRegionId(param.getRegionId());
        companyPageQuery.setName(param.getCompanyName());
        companyPageQuery.setPageNumber(param.getPageNumber());
        companyPageQuery.setPageSize(param.getPageSize());
        // 筛选掉管理企业
        companyPageQuery.setCompanyTypeList(Lists.newArrayList(1, 2, 3));
        PageVo<CompanyVO> pageVo = companyManage.queryList(companyPageQuery);
        // 获取企业信用信息
        Map<Long, List<NdCompanyCreditLevel>> listMap = companyCreditLevelService.list().stream()
            .collect(Collectors.groupingBy(NdCompanyCreditLevel::getCompanyId));
        if (pageVo.getTotal() != null && 0L != pageVo.getTotal()) {
            List<CompanyVO> companyVOList = new ArrayList<>(pageVo.getRecords());
            for (CompanyVO companyVO : companyVOList) {
                ResCompanyBasicCreditDTO resCompanyBasicCreditDTO = new ResCompanyBasicCreditDTO();
                BeanUtil.copyProperties(companyVO, resCompanyBasicCreditDTO);
                Company company = companyService.getById(companyVO.getId());
                BeanUtil.copyProperties(company, resCompanyBasicCreditDTO);
                resCompanyBasicCreditDTO.setRegionName(companyVO.getRegionName());
                resCompanyBasicCreditDTO.setCarCompanyType(CompanyTypeEnum.getDescByCode(company.getCompanyType()));
                resCompanyBasicCreditDTO.setDutyParagraph(company.getBusinessLicense());
                List<NdCompanyCreditLevel> creditLevelList = listMap.get(companyVO.getId());
                if (CollUtil.isNotEmpty(creditLevelList)) {
                    String year = String.valueOf(LocalDateTime.now().getYear());
                    // 筛选当前年份的数据
                    List<NdCompanyCreditLevel> levels =
                        creditLevelList.stream().filter(c -> year.equals(c.getYear())).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(levels)) {
                        NdCompanyCreditLevel creditLevel = levels.get(0);
                        resCompanyBasicCreditDTO.setBasicCreditScore(creditLevel.getBasicCreditScore());
                    }
                } else {
                    // 信用表中不存在该企业,设为0
                    log.info("企业信息等级表中不存在该企业{}", companyVO.getId());
                    resCompanyBasicCreditDTO.setBasicCreditScore(0);
                }
                result.add(resCompanyBasicCreditDTO);
            }
        }
        page.setTotal(pageVo.getTotal());
        page.setRecords(result);
        return page;
    }

    @Override
    public ResCompanyBasicCreditDetailDTO getCompanyBasicCreditDetail(Long companyId) {
        ResCompanyBasicCreditDetailDTO resCompanyBasicCreditDetailDTO = new ResCompanyBasicCreditDetailDTO();
        // 获取企业信息
        LambdaQueryWrapper<Company> wrapper = Wrappers.lambdaQuery(Company.class);
        ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl) AopContext.currentProxy();
        context.buildQuery(wrapper, companyId);
        Company company = companyService.getOne(wrapper);
        if (Objects.isNull(company)) {
            throw new BizException("企业不存在");
        }
        //Company company = companyService.getById(companyId);

        BeanUtil.copyProperties(company, resCompanyBasicCreditDetailDTO);

        // 对手机号和身份证号进行脱敏处理
        String contactPhone = company.getContactPhone();
        String encryptPhone = DesensitizedUtil.mobilePhone(contactPhone);
        resCompanyBasicCreditDetailDTO.setContactPhone(encryptPhone);

        CompanyBasicCredit companyBasicCredit =
            iCompanyBasicCreditService.getOne(new QueryWrapper<CompanyBasicCredit>().eq("company_id", companyId));
        BeanUtil.copyProperties(companyBasicCredit, resCompanyBasicCreditDetailDTO);
        if (company.getRegionId() != null && 0L != company.getRegionId()) {
            Region region = iRegionService.getById(company.getRegionId());
            resCompanyBasicCreditDetailDTO.setRegionCode(region.getRegionCode());
        }
        return resCompanyBasicCreditDetailDTO;
    }

    @Override
    public PageVo<ResCompanyCommonCreditDTO> getCompanyCommonCreditList(CompanyListParamDTO param) {
        PageVo<ResCompanyCommonCreditDTO> page = new PageVo<>();
        List<ResCompanyCommonCreditDTO> result = new ArrayList<>();
        CompanyPageQuery companyPageQuery = new CompanyPageQuery();
        companyPageQuery.setRegionId(param.getRegionId());
        companyPageQuery.setName(param.getCompanyName());
        companyPageQuery.setPageNumber(param.getPageNumber());
        companyPageQuery.setPageSize(param.getPageSize());
        companyPageQuery.setBlackList(param.getBlackList());
        PageVo<CompanyVO> pageVo = companyManage.queryList(companyPageQuery);
        // 获取企业信用信息
        Map<Long, List<NdCompanyCreditLevel>> listMap = companyCreditLevelService.list().stream()
            .collect(Collectors.groupingBy(NdCompanyCreditLevel::getCompanyId));
        if (pageVo.getTotal() != null && 0L != pageVo.getTotal()) {
            List<CompanyVO> companyVOList = new ArrayList<>(pageVo.getRecords());
            for (CompanyVO companyVO : companyVOList) {
                ResCompanyCommonCreditDTO resCompanyCommonCreditDTO = new ResCompanyCommonCreditDTO();
                BeanUtil.copyProperties(companyVO, resCompanyCommonCreditDTO);
                List<NdCompanyCreditLevel> creditLevelList = listMap.get(companyVO.getId());
                if (CollUtil.isNotEmpty(creditLevelList)) {
                    String year = String.valueOf(LocalDateTime.now().getYear());
                    // 筛选当前年份的数据
                    List<NdCompanyCreditLevel> levels =
                        creditLevelList.stream().filter(c -> year.equals(c.getYear())).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(levels)) {
                        NdCompanyCreditLevel creditLevel = levels.get(0);
                        resCompanyCommonCreditDTO.setCommonCreditScore(creditLevel.getCommonCreditScore());
                    }
                } else {
                    // 信用表中不存在该企业,设为0
                    log.info("企业信息等级表中不存在该企业{}", companyVO.getId());
                    resCompanyCommonCreditDTO.setCommonCreditScore(0);
                }
                result.add(resCompanyCommonCreditDTO);
            }
        }
        page.setTotal(pageVo.getTotal());
        page.setRecords(result);
        return page;
    }

    @Override
    public void companyListExport(HttpServletResponse response, CompanyListParamDTO param) {
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        PageVo<ResCompanyArchivesDTO> page = getCompanyList(param);

        List<ResCompanyArchivesDTO> collect = (List<ResCompanyArchivesDTO>)page.getRecords();

        String fileName = "企业列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), ResCompanyArchivesDTO.class).autoCloseStream(false)
                .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void companyBasicCreditListExport(HttpServletResponse response, CompanyListParamDTO param) {
        PageVo<ResCompanyBasicCreditDTO> page = getCompanyBasicCreditList(param);
        List<ResCompanyBasicCreditDTO> collect = (List<ResCompanyBasicCreditDTO>)page.getRecords();
        String fileName = "企业基本信用列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), ResCompanyBasicCreditDTO.class).autoCloseStream(false)
                .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void companyCommonCreditListExport(HttpServletResponse response, CompanyListParamDTO param) {
        PageVo<ResCompanyCommonCreditDTO> page = getCompanyCommonCreditList(param);
        List<ResCompanyCommonCreditDTO> collect = (List<ResCompanyCommonCreditDTO>)page.getRecords();
        String fileName = "企业公共信用列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), ResCompanyCommonCreditDTO.class).autoCloseStream(false)
                .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void companyCertificateInformationListExport(HttpServletResponse response, CompanyListParamDTO param) {
        param.setPageNumber(1);
        param.setPageSize(10000);
        PageVo<ResCompanyArchivesDTO> page = getCompanyList(param);
        List<ResCompanyArchivesDTO> collect = (List<ResCompanyArchivesDTO>)page.getRecords();

        String fileName = "企业证书信息列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), ResCompanyArchivesDTO.class).autoCloseStream(false)
                .registerWriteHandler(ExcelExportStyle.formalStyle()).sheet(fileName).doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public PageVo<ResNotGetOnCarRecordDTO> getNotOnCarList(ReqNotGetOnCarDTO param) {
        Page<CompanyVehicleNotGetOn> page = param.page();
        LambdaQueryWrapper<CompanyVehicleNotGetOn> wrapper = Wrappers.lambdaQuery(CompanyVehicleNotGetOn.class);
        ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl) AopContext.currentProxy();
        context.buildNotOnCarQuery(wrapper,param);
        Page<CompanyVehicleNotGetOn> notGetOnPage = companyVehicleNotGetOnService.page(page, wrapper);
        List<ResNotGetOnCarRecordDTO> resData = notGetOnPage.getRecords().stream().map(c -> {
            ResNotGetOnCarRecordDTO res = new ResNotGetOnCarRecordDTO();
            res.setId(c.getId());
            res.setCarPlate(c.getCarPlate());
            res.setTime(c.getTime());
            return res;
        }).collect(Collectors.toList());
        return PageVo.of(resData, page.getTotal());
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_COMPANY)
    public void buildNotOnCarQuery(LambdaQueryWrapper<CompanyVehicleNotGetOn> wrapper, ReqNotGetOnCarDTO param) {
        wrapper.eq(CompanyVehicleNotGetOn::getCompanyId, param.getCompanyId())
                .eq(Objects.nonNull(param.getCarPlate()), CompanyVehicleNotGetOn::getCarPlate, param.getCarPlate())
                .eq(Objects.nonNull(param.getQueryTime()), CompanyVehicleNotGetOn::getTime, param.getQueryTime());
    }

    @Override
    public CompanySecurityInfoVO getCompanySecurityInfo(Long companyId) {
        CompanySecurityInfoVO vo = new CompanySecurityInfoVO();
        // 默认显示查询时间所在年度的信用等级
        String year = String.valueOf(LocalDateTime.now().getYear());
        // 获取企业信用等级信息
        NdCompanyCreditLevel creditLevel =
            companyCreditLevelService.getOne(Wrappers.lambdaQuery(NdCompanyCreditLevel.class)
                .eq(NdCompanyCreditLevel::getCompanyId, companyId).eq(NdCompanyCreditLevel::getYear, year));
        if (Objects.nonNull(creditLevel)) {
            vo.setCreditLevel(creditLevel.getLevel());
            vo.setCreditLevelName(CompanyCreditLevelEnum.getDescByCode(creditLevel.getLevel()));
            vo.setCompanyCreditEvaluateTotalScore(creditLevel.getScore());
            vo.setCommonCreditScore(creditLevel.getCommonCreditScore());
            vo.setBasicCreditScore(creditLevel.getBasicCreditScore());
            vo.setSafeProductCreditScore(creditLevel.getSafeProductCreditScore());
            vo.setIndustryRegulateCreditScore(creditLevel.getIndustryRegulateCreditScore());
            vo.setIndustryHonorBonus(creditLevel.getIndustryHonorBonus());
        }

        // 获取企业风险等级信息
        WarnAnalysisCompany warnAnalysisCompany = warnAnalysisCompanyService
            .getOne(Wrappers.lambdaQuery(WarnAnalysisCompany.class).eq(WarnAnalysisCompany::getCompanyId, companyId));
        if (Objects.nonNull(warnAnalysisCompany)) {
            vo.setDangerLevel(warnAnalysisCompany.getDangerLevel());
            vo.setDangerLevelName(DangerLevelEnum.getDescByCode(warnAnalysisCompany.getDangerLevel()));
            vo.setCompanySafeRiskScore(warnAnalysisCompany.getTotalScore());
            vo.setViolationCnt(warnAnalysisCompany.getViolationCount());
            vo.setOutDangerCnt(warnAnalysisCompany.getDangerCount());
            vo.setInjuryCnt(warnAnalysisCompany.getInjuredCount());
            vo.setDeadCnt(warnAnalysisCompany.getDeadCount());
        }
        return vo;
    }

    public Company saveCompany(CompanySaveDTO data) {
        Company company = companyService.save(data, null);
        companiesCacheHelper.refresh(company.getId());
        return company;
    }

    @Override
    public PageVo<ResCompanyArchivesDTO> queryToBeAudit(CompanyAuditPageQuery param) {

        Integer pageNumber = param.getPageNumber();
        Integer pageSize = param.getPageSize();
        Integer productCompanyType = param.getProductCompanyType();

        LambdaQueryWrapper<Company> wrapper = Wrappers.lambdaQuery(Company.class);
        ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl)AopContext.currentProxy();
        // 判断登录用户的角色
        UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
        Long roleId = userInfoDetails.getRoleId();
        // 如果是区县管理员
        if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId)) {
            context.searchRegionTobeAuditWrapper(wrapper, param);
        } else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) {
            context.searchCityTobeAuditWrapper(wrapper, param);
        } else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId) ||
                UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(roleId)){
            context.searchAllTobeAuditWrapper(wrapper,param);
        } else {
            return PageVo.empty();
        }
        List<Company> companyList = companyService.list(wrapper);
        Map<Long, List<CompanyTypeRelated>> companyTypeRelatedMap =
            companyTypeRelatedService.list().stream().collect(Collectors.groupingBy(CompanyTypeRelated::getCompanyId));

        // 如果具体到生产企业类型筛选
        if (Objects.nonNull(productCompanyType)) {
            // 从企业类型关联表中查出对应的企业
            List<CompanyTypeRelated> relatedList = companyTypeRelatedService.list().stream().filter(c -> {
                Long value = productCompanyType.longValue();
                Long companyTypeId = c.getCompanyTypeId();
                if (value.equals(companyTypeId)) {
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            // 去重
            List<Long> companies =
                relatedList.stream().map(CompanyTypeRelated::getCompanyId).distinct().collect(Collectors.toList());
            if (CollUtil.isNotEmpty(companies)) {
                companyList =
                    companyList.stream().filter(d -> companies.contains(d.getId())).collect(Collectors.toList());
            }
        }

        List<Company> records =
            companyList.stream().skip((long)(pageNumber - 1) * pageSize).limit(pageSize).collect(Collectors.toList());

        List<ResCompanyArchivesDTO> res = records.stream().map(w -> {
            ResCompanyArchivesDTO dto = new ResCompanyArchivesDTO();
            BeanUtil.copyProperties(w, dto);
            CodeUtil.searchRegionName(dto);
            if (Objects.nonNull(w.getCompanyType())) {
                // 如果是生产企业,展示具体的企业类型
                if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(w.getCompanyType())) {
                    List<CompanyTypeRelated> relatedList = companyTypeRelatedMap.get(w.getId());
                    List<String> nameList = relatedList.stream()
                        .map(r -> ProductCompanyType.getDescByCode(r.getCompanyTypeId())).collect(Collectors.toList());
                    String typeName = nameList.stream().collect(Collectors.joining(StrPool.COMMA));
                    dto.setCarCompanyType(typeName);
                } else {
                    dto.setCarCompanyType(CompanyTypeEnum.getDescByCode(w.getCompanyType()));
                }
            }
            return dto;
        }).collect(Collectors.toList());
        return PageVo.of(res, companyList.size());
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    private void searchAllTobeAuditWrapper(LambdaQueryWrapper<Company> wrapper, CompanyAuditPageQuery param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName())
                .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType())
                .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus())
                .and(wp -> wp.eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT.getCode())
                        .or()
                        .eq(Company::getRegionAuditStatus,AuditStateEnum.AUDIT.getCode()))
                .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn);
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void searchCityTobeAuditWrapper(LambdaQueryWrapper<Company> wrapper, CompanyAuditPageQuery param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName())
            .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType())
            .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus())
            .eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT.getCode())
            .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn);
    }

    @Override
    public PageVo<ResCompanyArchivesDTO> queryAuditedList(CompanyAuditPageQuery param) {
        Integer pageNumber = param.getPageNumber();
        Integer pageSize = param.getPageSize();
        Integer productCompanyType = param.getProductCompanyType();

        LambdaQueryWrapper<Company> wrapper = Wrappers.lambdaQuery(Company.class);
        ICompanyArchivesServiceImpl context = (ICompanyArchivesServiceImpl)AopContext.currentProxy();
        // 判断登录用户的角色
        UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
        Long roleId = userInfoDetails.getRoleId();
        // 如果是区县管理员
        if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId)) {
            context.searchRegionAuditedWrapper(wrapper, param);
        } else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) {
            context.searchCityAuditedWrapper(wrapper, param);
        }else if (UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId) ||
                UserRoleTypeEnum.SYSTEM_ROLE_ID.getId().equals(roleId)) {
            context.searchAllAuditedWrapper(wrapper, param);
        } else {
            return PageVo.empty();
        }

        List<Company> companyList = companyService.list(wrapper);
        Map<Long, List<CompanyTypeRelated>> companyTypeRelatedMap =
            companyTypeRelatedService.list().stream().collect(Collectors.groupingBy(CompanyTypeRelated::getCompanyId));

        // 如果具体到生产企业类型筛选
        if (Objects.nonNull(productCompanyType)) {
            // 从企业类型关联表中查出对应的企业
            List<CompanyTypeRelated> relatedList = companyTypeRelatedService.list().stream().filter(c -> {
                Long value = productCompanyType.longValue();
                Long companyTypeId = c.getCompanyTypeId();
                if (value.equals(companyTypeId)) {
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            // 去重
            List<Long> companies =
                relatedList.stream().map(CompanyTypeRelated::getCompanyId).distinct().collect(Collectors.toList());
            if (CollUtil.isNotEmpty(companies)) {
                companyList =
                    companyList.stream().filter(d -> companies.contains(d.getId())).collect(Collectors.toList());
            }
        }

        List<Company> records =
            companyList.stream().skip((long)(pageNumber - 1) * pageSize).limit(pageSize).collect(Collectors.toList());

        List<ResCompanyArchivesDTO> res = records.stream().map(w -> {
            ResCompanyArchivesDTO dto = new ResCompanyArchivesDTO();
            BeanUtil.copyProperties(w, dto);
            CodeUtil.searchRegionName(dto);
            if (Objects.nonNull(w.getCompanyType())) {
                // 如果是生产企业,展示具体的企业类型
                if (CompanyTypeEnum.PRODUCT_BU.getCode().equals(w.getCompanyType())) {
                    List<CompanyTypeRelated> relatedList = companyTypeRelatedMap.get(w.getId());
                    List<String> nameList = relatedList.stream()
                        .map(r -> ProductCompanyType.getDescByCode(r.getCompanyTypeId())).collect(Collectors.toList());
                    String typeName = nameList.stream().collect(Collectors.joining(StrPool.COMMA));
                    dto.setCarCompanyType(typeName);
                } else {
                    dto.setCarCompanyType(CompanyTypeEnum.getDescByCode(w.getCompanyType()));
                }
            }
            return dto;
        }).collect(Collectors.toList());
        return PageVo.of(res, companyList.size());
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    private void searchAllAuditedWrapper(LambdaQueryWrapper<Company> wrapper, CompanyAuditPageQuery param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName())
                .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType())
                .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus())
                .and(wp -> wp.eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode())
                        .or()
                        .eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode())
                        .or()
                        .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode())
                        .or()
                        .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode()))
                .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn);
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void searchCityAuditedWrapper(LambdaQueryWrapper<Company> wrapper, CompanyAuditPageQuery param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName())
            .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType())
            .eq(Objects.nonNull(param.getAuditStatus()), Company::getCityAuditStatus, param.getAuditStatus())
            .and(wp -> wp.eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode()).or()
                .eq(Company::getCityAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode()))
            .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean audit(CompanyAuditDTO data, Long userId) {
        VUtils.isTrue(!AuditStateEnum.AUDIT_SUCCESS.getCode().equals(data.getAuditStatus())
            && !AuditStateEnum.AUDIT_FAIL.getCode().equals(data.getAuditStatus())).throwMessage("请确认传入的审核code正确");
        Company company = companyService.getById(data.getId());
        VUtils.isTrueFormat(Objects.isNull(company)).throwMessage(ExceptionCode.OPERATION_EX.getCode(), "修改企业 {} 为空",
            data.getId());
        UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
        Long roleId = userInfoDetails.getRoleId();
        // 如果是区县散办管理员
        if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(roleId)) {
            company.setRegionAuditStatus(data.getAuditStatus());
            company.setRegionAuditBy(userId);
            company.setRegionAuditTime(LocalDateTime.now());
            company.setRegionAuditMind(data.getAuditMind());
        }
        // 当且仅当登录用户是市级散办管理员账号,且审核通过,才更新企业审核状态为通过，并创建企业账号信息
        else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(roleId)) {
            company.setCityAuditStatus(data.getAuditStatus());
            company.setCityAuditBy(userId);
            company.setCityAuditTime(LocalDateTime.now());
            company.setCityAuditMind(data.getAuditMind());
            // 市散办审核通过
            if (AuditStateEnum.AUDIT_SUCCESS.getCode().equals(data.getAuditStatus())) {
                // 创建企业用户账号
                NdUserInfo userInfo = new NdUserInfo();
                userInfo.setCanLogin(UserCanLoginEnum.CAN_LOGIN.getCode());
                userInfo.setUsername(company.getName());
                userInfo.setCompanyId(company.getId());
                userInfo.setCreateOn(LocalDateTime.now());
                userInfo.setUpdateOn(LocalDateTime.now());
                userInfoService.save(userInfo);

                Long userInfoId = userInfo.getId();
                NdUserAuth userAuth = new NdUserAuth();
                userAuth.setUserId(userInfoId);
                userAuth.setIdentifier(company.getName());
                userAuth.setCredential(passwordEncoder.encode("123456Aa"));
                userAuth.setAuthType(AuthTypeEnum.ACCOUNT_PASSWORD.getKey());
                userAuth.setIsAvailable(true);
                ndUserAuthService.save(userAuth);

                UserRole userRole = new UserRole();
                userRole.setUserId(userInfoId);
                userRole.setRoleId(UserRoleTypeEnum.COMPANY_INFO_OFFICER_ROLE_ID.getId());
                userRoleService.save(userRole);
            }

        }
        // 最后修改人
        company.setUpdateBy(userId);
        company.setUpdateOn(LocalDateTime.now());
        return companyService.updateById(company);
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void searchRegionAuditedWrapper(LambdaQueryWrapper<Company> wrapper, CompanyAuditPageQuery param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName())
            .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType())
            .eq(Objects.nonNull(param.getAuditStatus()), Company::getRegionAuditStatus, param.getAuditStatus())
            .and(wp -> wp.eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_SUCCESS.getCode()).or()
                .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT_FAIL.getCode()))
            .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn);
    }

    @LambdaDataScope
    @BuildChildrenRegionWrapper
    public void searchRegionTobeAuditWrapper(LambdaQueryWrapper<Company> wrapper, CompanyAuditPageQuery param) {
        wrapper.like(StringUtils.isNotBlank(param.getCompanyName()), Company::getBankName, param.getCompanyName())
            .eq(Objects.nonNull(param.getCompanyType()), Company::getCompanyType, param.getCompanyType())
            .eq(Objects.nonNull(param.getAuditStatus()), Company::getRegionAuditStatus, param.getAuditStatus())
            .eq(Company::getRegionAuditStatus, AuditStateEnum.AUDIT.getCode())
            .orderBy(Boolean.TRUE, Boolean.FALSE, Company::getUpdateOn);
    }
}
