package com.ningdatech.carapi.company.manage;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
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.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.carapi.common.constant.UserRoleTypeEnum;
import com.ningdatech.carapi.common.contants.DefValConstants;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.company.entity.CompanySecurityCommitment;
import com.ningdatech.carapi.company.entity.CompanySecurityGovernment;
import com.ningdatech.carapi.company.entity.CompanySecurityProductExecute;
import com.ningdatech.carapi.company.entity.CompanySecurityProductRegulation;
import com.ningdatech.carapi.company.entity.dto.*;
import com.ningdatech.carapi.company.entity.vo.ComSecProExeVO;
import com.ningdatech.carapi.company.entity.vo.ComSecProRegVO;
import com.ningdatech.carapi.company.entity.vo.CompanySecurityCommitmentVO;
import com.ningdatech.carapi.company.entity.vo.CompanySecurityGovernmentVO;
import com.ningdatech.carapi.company.service.ICompanySecurityCommitmentService;
import com.ningdatech.carapi.company.service.ICompanySecurityGovernmentService;
import com.ningdatech.carapi.company.service.ICompanySecurityProductExecuteFileService;
import com.ningdatech.carapi.company.service.ICompanySecurityProductRegulationsFileService;
import com.ningdatech.carapi.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.datascope.contants.LambdaDataScopeTypeEnum;
import com.ningdatech.carapi.sys.entity.Company;
import com.ningdatech.carapi.sys.service.CompanyService;
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.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @Classname CompanySecurityManage
 * @Description
 * @Date 2023/5/23 17:32
 * @Author PoffyZhang
 */
@Component
@Slf4j
@AllArgsConstructor
public class CompanySecurityManage {

    private final ICompanySecurityCommitmentService commitmentService;
    private final ICompanySecurityGovernmentService governmentService;
    private final CompanyService companyService;
    private final ICompanySecurityProductRegulationsFileService regulationsFileService;
    private final ICompanySecurityProductExecuteFileService executeFileService;

    /**
     * 上传安全承诺书
     * @param dto
     * @return
     */
    public Boolean uploadCommitment(UploadCommitmentDTO dto) {
        CompanySecurityCommitment commitment = BeanUtil.copyProperties(dto,CompanySecurityCommitment.class);
        commitment.setCreateOn(LocalDateTime.now());
        return commitmentService.save(commitment);
    }

    /**
     * 上传安全管理机构
     * @param dto
     * @return
     */
    public Boolean uploadGovernment(UploadGovernmentDTO dto) {
        CompanySecurityGovernment government = BeanUtil.copyProperties(dto,CompanySecurityGovernment.class);
        government.setCreateOn(LocalDateTime.now());
        return governmentService.save(government);
    }

    public PageVo<CompanySecurityCommitmentVO> pageCommitments(CompanySecurityCommitmentParam param) {
        Page<CompanySecurityCommitment> page = param.page();

        LambdaQueryWrapper<CompanySecurityCommitment> wrapper = Wrappers.lambdaQuery(CompanySecurityCommitment.class)
                .ge(Objects.nonNull(param.getStartTime()), CompanySecurityCommitment::getCreateOn, param.getStartTime())
                .le(Objects.nonNull(param.getEndTime()), CompanySecurityCommitment::getCreateOn, param.getEndTime())
                .eq(Objects.nonNull(param.getRegionId()), CompanySecurityCommitment::getRegionId, param.getRegionId());

        //如果需要公司名称模糊匹配
        if(StringUtils.isNotBlank(param.getCompanyName())){
            List<Company> companies = companyService.list(Wrappers.lambdaQuery(Company.class)
                    .like(Company::getName, param.getCompanyName()));
            if(CollUtil.isEmpty(companies)) {
                return PageVo.empty();
            }
            List<Long> companyIds = companies.stream().map(Company::getId).collect(Collectors.toList());
            wrapper.in(CompanySecurityCommitment::getCompanyId,companyIds);

        }

        commitmentService.pageDataScope(page,wrapper,param);
        if(0L == page.getTotal()){
            return PageVo.empty();
        }
        List<CompanySecurityCommitmentVO> res = page.getRecords().stream().map(data -> {
            CompanySecurityCommitmentVO vo = BeanUtil.copyProperties(data,CompanySecurityCommitmentVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res,page.getTotal());
    }



    public PageVo<CompanySecurityGovernmentVO> pageGovernments(CompanySecurityCommitmentParam param) {
        // Page<CompanySecurityGovernment> page = param.page();

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

        UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
        Long roleId = userInfoDetails.getRoleId();

        LambdaQueryWrapper<CompanySecurityGovernment> wrapper = Wrappers.lambdaQuery(CompanySecurityGovernment.class)
                .ge(Objects.nonNull(param.getStartTime()), CompanySecurityGovernment::getCreateOn, param.getStartTime())
                .le(Objects.nonNull(param.getEndTime()), CompanySecurityGovernment::getCreateOn, param.getEndTime())
                .like(Objects.nonNull(param.getDocNature()),CompanySecurityGovernment::getDocNature,param.getDocNature())
                .like(Objects.nonNull(param.getDepartmentName()),CompanySecurityGovernment::getDepartmentName,param.getDepartmentName())
                .eq(Objects.nonNull(param.getRegionId()), CompanySecurityGovernment::getRegionId, param.getRegionId());
        //如果需要公司名称模糊匹配
        if(StringUtils.isNotBlank(param.getCompanyName())){
            List<Company> companies = companyService.list(Wrappers.lambdaQuery(Company.class)
                    .like(Company::getName, param.getCompanyName()));
            if(CollUtil.isEmpty(companies)) {
                return PageVo.empty();
            }
            List<Long> companyIds = companies.stream().map(Company::getId).collect(Collectors.toList());
            wrapper.in(CompanySecurityGovernment::getCompanyId,companyIds);
        }

        List<CompanySecurityGovernment> governmentList = governmentService.dataScopeList(wrapper, param);

        // 省级部门上传的文件，下级账号也要能看到
        if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) {
            LambdaQueryWrapper<CompanySecurityGovernment> queryWrapper = Wrappers.lambdaQuery(CompanySecurityGovernment.class);
            if (Objects.nonNull(param.getRegionId())){
                queryWrapper.eq(CompanySecurityGovernment::getRegionId,param.getRegionId());
            }else {
                queryWrapper.eq(CompanySecurityGovernment::getRegionId, DefValConstants.ZJREGION_ID);
            }
            queryWrapper.ge(Objects.nonNull(param.getStartTime()), CompanySecurityGovernment::getCreateOn, param.getStartTime())
                    .le(Objects.nonNull(param.getEndTime()), CompanySecurityGovernment::getCreateOn, param.getEndTime())
                    .like(Objects.nonNull(param.getDocNature()),CompanySecurityGovernment::getDocNature,param.getDocNature())
                    .like(Objects.nonNull(param.getDepartmentName()),CompanySecurityGovernment::getDepartmentName,param.getDepartmentName());
            //如果需要公司名称模糊匹配
            if(StringUtils.isNotBlank(param.getCompanyName())){
                List<Company> companies = companyService.list(Wrappers.lambdaQuery(Company.class)
                        .like(Company::getName, param.getCompanyName()));
                List<Long> companyIds = companies.stream().map(Company::getId).collect(Collectors.toList());
                queryWrapper.in(CompanySecurityGovernment::getCompanyId,companyIds);
            }
            List<CompanySecurityGovernment> governments = governmentService.list(queryWrapper);
            governmentList.addAll(governments);
        }

        if (CollUtil.isEmpty(governmentList)){
            return PageVo.empty();
        }

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

        List<CompanySecurityGovernmentVO> res = records.stream().map(data -> {
            CompanySecurityGovernmentVO vo = BeanUtil.copyProperties(data,CompanySecurityGovernmentVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(res,governmentList.size());


        // governmentService.pageDataScope(page,wrapper,param);
        //if(0L == page.getTotal()){
        //    return PageVo.empty();
        //}

        //List<CompanySecurityGovernmentVO> res = page.getRecords().stream().map(data -> {
        //    CompanySecurityGovernmentVO vo = BeanUtil.copyProperties(data,CompanySecurityGovernmentVO.class);
        //    CodeUtil.searchCompanyNameAndRegionName(vo);
        //    return vo;
        //}).collect(Collectors.toList());
        //return PageVo.of(res,page.getTotal());
    }

    public PageVo<ComSecProRegVO> pageRegulations(CompanySecurityProductRegulationParam param) {
        // Page<CompanySecurityProductRegulation> page = param.page();
        UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
        Long roleId = userInfoDetails.getRoleId();
        Integer pageNumber = param.getPageNumber();
        Integer pageSize = param.getPageSize();
        LambdaQueryWrapper<CompanySecurityProductRegulation> wrapper = Wrappers.lambdaQuery(CompanySecurityProductRegulation.class)
                .eq(CompanySecurityProductRegulation::getFileType,param.getFileType())
                .ge(Objects.nonNull(param.getStartTime()), CompanySecurityProductRegulation::getCreateOn, param.getStartTime())
                .le(Objects.nonNull(param.getEndTime()), CompanySecurityProductRegulation::getCreateOn, param.getEndTime())
                .like(Objects.nonNull(param.getFileName()),CompanySecurityProductRegulation::getFileName,param.getFileName())
                .like(Objects.nonNull(param.getCompanyName()), CompanySecurityProductRegulation::getCompanyName, param.getCompanyName());

        List<CompanySecurityProductRegulation> regulationList = regulationsFileService.dataScopeList(wrapper, param);

        // 省级部门上传的文件(所属区域为省级)，按照文件类型，下级账号也要能看到
        if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) {
            List<CompanySecurityProductRegulation> regulations = regulationsFileService.list(Wrappers.lambdaQuery(CompanySecurityProductRegulation.class)
                    .eq(CompanySecurityProductRegulation::getRegionId, DefValConstants.ZJREGION_ID)
                    .eq(CompanySecurityProductRegulation::getFileType,param.getFileType()));
            regulationList.addAll(regulations);
        }

        if (CollUtil.isEmpty(regulationList)){
            return PageVo.empty();
        }

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

        List<ComSecProRegVO> res = records.stream()
                .map(data -> {
                    ComSecProRegVO vo = BeanUtil.copyProperties(data, ComSecProRegVO.class);
                    CodeUtil.searchCompanyNameAndRegionName(vo);
                    return vo;
                })
                .collect(Collectors.toList());
        return PageVo.of(res,regulationList.size());

        //regulationsFileService.pageDataScope(page,wrapper,param);
        //if(0L == page.getTotal()){
        //    return PageVo.empty();
        //}
        //List<ComSecProRegVO> res = page.getRecords().stream().map(data -> {
        //    ComSecProRegVO vo = BeanUtil.copyProperties(data,ComSecProRegVO.class);
        //    return vo;
        //}).collect(Collectors.toList());
        //return PageVo.of(res,page.getTotal());
    }

    public Boolean uploadRegulation(UploadRegulationDTO dto) {
        CompanySecurityProductRegulation regulation = BeanUtil.copyProperties(dto,CompanySecurityProductRegulation.class);
        regulation.setCreateOn(LocalDateTime.now());
        regulation.setCreateBy(LoginUserUtil.getUserId());
        regulation.setUpdateOn(LocalDateTime.now());
        regulation.setUpdateBy(LoginUserUtil.getUserId());
        return regulationsFileService.save(regulation);
    }

    public PageVo<ComSecProExeVO> pageExecutes(CompanySecurityProductExecuteParam param) {
        //Page<CompanySecurityProductExecute> page = param.page();
        Integer pageNumber = param.getPageNumber();
        Integer pageSize = param.getPageSize();

        UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
        Long roleId = userInfoDetails.getRoleId();

        LambdaQueryWrapper<CompanySecurityProductExecute> wrapper = Wrappers.lambdaQuery(CompanySecurityProductExecute.class)
                .ge(Objects.nonNull(param.getStartTime()), CompanySecurityProductExecute::getCreateOn, param.getStartTime())
                .le(Objects.nonNull(param.getEndTime()), CompanySecurityProductExecute::getCreateOn, param.getEndTime())
                .like(Objects.nonNull(param.getFileName()),CompanySecurityProductExecute::getFileName,param.getFileName());
        List<CompanySecurityProductExecute> executeList = executeFileService.dataScopeList(wrapper, param);
        // 省级部门上传的文件(所属区域为省级)，下级账号也要能看到
        if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)) {
            List<CompanySecurityProductExecute> executes = executeFileService.list(Wrappers.lambdaQuery(CompanySecurityProductExecute.class)
                    .eq(CompanySecurityProductExecute::getRegionId, DefValConstants.ZJREGION_ID));
            executeList.addAll(executes);
        }

        if (CollUtil.isEmpty(executeList)){
            return PageVo.empty();
        }

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

        List<ComSecProExeVO> res = records.stream()
                .map(data -> {
                    ComSecProExeVO vo = BeanUtil.copyProperties(data, ComSecProExeVO.class);
                    CodeUtil.searchRegionName(vo);
                    return vo;
                })
                .collect(Collectors.toList());
        return PageVo.of(res,executeList.size());

        //executeFileService.pageDataScope(page,wrapper,param);
        //if(0L == page.getTotal()){
        //    return PageVo.empty();
        //}
        //List<ComSecProExeVO> res = page.getRecords().stream().map(data -> {
        //    ComSecProExeVO vo = BeanUtil.copyProperties(data,ComSecProExeVO.class);
        //    return vo;
        //}).collect(Collectors.toList());
        //return PageVo.of(res,page.getTotal());
    }

    public Boolean uploadExecution(UploadExecutionDTO dto) {
        CompanySecurityProductExecute execution = BeanUtil.copyProperties(dto,CompanySecurityProductExecute.class);
        execution.setCreateOn(LocalDateTime.now());
        execution.setCreateBy(LoginUserUtil.getUserId());
        execution.setUpdateOn(LocalDateTime.now());
        execution.setUpdateBy(LoginUserUtil.getUserId());
        return executeFileService.save(execution);
    }

    public void deleteGovernmentFile(Long id, Long roleId) {

        LambdaQueryWrapper<CompanySecurityGovernment> wrapper = Wrappers.lambdaQuery(CompanySecurityGovernment.class);
        CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy();
        context.buildQuery(wrapper, id);
        CompanySecurityGovernment government = governmentService.getOne(wrapper);
        if (Objects.isNull(government)){
            throw new BizException("文件无法删除!");
        }
        //CompanySecurityGovernment government = governmentService.getById(id);

        // 如果文件是省级部门上传的文件，只有省级管理员角色可以删除
        Long regionId = government.getRegionId();
        if (Objects.nonNull(regionId) &&
                DefValConstants.ZJREGION_ID.equals(regionId)){
            // 判断登录用户角色是否为省管理员
            if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){
                throw new BizException("您没有权限删除该文件!");
            }
        }
        governmentService.deleteById(id);
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildQuery(LambdaQueryWrapper<CompanySecurityGovernment> wrapper, Long id) {
        wrapper.eq(CompanySecurityGovernment::getId,id);
    }

    public void incrementDownCount(Long id) {
        executeFileService.incrementDownCount(id);
    }

    public void deleteCommitmentFile(Long id, Long roleId) {

        LambdaQueryWrapper<CompanySecurityCommitment> wrapper = Wrappers.lambdaQuery(CompanySecurityCommitment.class);
        CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy();
        context.buildCommitmentQuery(wrapper, id);
        CompanySecurityCommitment commitment = commitmentService.getOne(wrapper);
        if (Objects.isNull(commitment)){
            throw new BizException("文件无法删除!");
        }
        //CompanySecurityCommitment commitment = commitmentService.getById(id);
        // 如果文件是省级部门上传的文件，只有省级管理员角色可以删除
        Long regionId = commitment.getRegionId();
        if (Objects.nonNull(regionId) &&
                DefValConstants.ZJREGION_ID.equals(regionId)){
            // 判断登录用户角色是否为省管理员
            if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){
                throw new BizException("您没有权限删除该文件!");
            }
        }
        commitmentService.deleteById(id);
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildCommitmentQuery(LambdaQueryWrapper<CompanySecurityCommitment> wrapper, Long id) {
        wrapper.eq(CompanySecurityCommitment::getId,id);
    }

    public void deleteRegulationFile(Long id, Long roleId) {

        LambdaQueryWrapper<CompanySecurityProductRegulation> wrapper = Wrappers.lambdaQuery(CompanySecurityProductRegulation.class);
        CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy();
        context.buildRegulationQuery(wrapper, id);
        CompanySecurityProductRegulation regulation = regulationsFileService.getOne(wrapper);
        if (Objects.isNull(regulation)){
            throw new BizException("文件无法删除!");
        }
        // CompanySecurityProductRegulation regulation = regulationsFileService.getById(id);

        // 如果文件是省级部门上传的文件，只有省级管理员角色可以删除
        Long regionId = regulation.getRegionId();
        if (Objects.nonNull(regionId) &&
                DefValConstants.ZJREGION_ID.equals(regionId)){
            // 判断登录用户角色是否为省管理员
            if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){
                throw new BizException("您没有权限删除该文件!");
            }
        }
        regulationsFileService.deleteById(id);
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ALL)
    public void buildRegulationQuery(LambdaQueryWrapper<CompanySecurityProductRegulation> wrapper, Long id) {
        wrapper.eq(CompanySecurityProductRegulation::getId,id);
    }

    public void deleteExecuteFile(Long id, Long roleId) {

        LambdaQueryWrapper<CompanySecurityProductExecute> wrapper = Wrappers.lambdaQuery(CompanySecurityProductExecute.class);
        CompanySecurityManage context = (CompanySecurityManage) AopContext.currentProxy();
        context.buildExecuteQuery(wrapper, id);
        CompanySecurityProductExecute execute = executeFileService.getOne(wrapper);
        if (Objects.isNull(execute)){
            throw new BizException("文件无法删除!");
        }
        // CompanySecurityProductExecute execute = executeFileService.getById(id);
        // 如果文件是省级部门上传的文件，只有省级管理员角色可以删除
        Long regionId = execute.getRegionId();
        if (Objects.nonNull(regionId) &&
                DefValConstants.ZJREGION_ID.equals(regionId)){
            // 判断登录用户角色是否为省管理员
            if (!UserRoleTypeEnum.SYSTEM_ADMIN_ROLE_ID.getId().equals(roleId)){
                throw new BizException("您没有权限删除该文件!");
            }
        }
        executeFileService.deleteById(id);
    }

    @LambdaDataScope(type = LambdaDataScopeTypeEnum.ONLY_REGION)
    public void buildExecuteQuery(LambdaQueryWrapper<CompanySecurityProductExecute> wrapper, Long id) {
        wrapper.eq(CompanySecurityProductExecute::getId,id);
    }
}
