package com.yccrc.kede.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yccrc.common.core.domain.entity.SysUser;
import com.yccrc.common.core.redis.RedisCache;
import com.yccrc.common.exception.ServiceException;
import com.yccrc.common.utils.PageUtils;
import com.yccrc.common.utils.SecurityUtils;
import com.yccrc.common.utils.StringUtils;
import com.yccrc.kede.domain.Attach;
import com.yccrc.kede.domain.Enterprise;
import com.yccrc.kede.domain.Project;
import com.yccrc.kede.domain.ProjectLog;
import com.yccrc.kede.enums.AttachTypeEnum;
import com.yccrc.kede.mapper.ProjectMapper;
import com.yccrc.kede.service.*;
import com.yccrc.kede.vo.*;
import com.yccrc.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 项目信息Service业务层处理
 *
 * @author yccrc
 * @date 2022-04-25
 */
@Service
@Slf4j
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {
    @Autowired
    IProjectLogService projectLogService;

    @Autowired
    ISysUserService userService;

    @Autowired
    private INotifyService notifyService;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private IAttachService attachService;
    @Autowired
    private RedisCache redisCache;

    @Override
    public Page<ProjectListVO> selectProject(ProjectQueryVO entity) {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>()
                .eq(entity.getProvinceId() != null, "b.province_id", entity.getProvinceId())
                .eq(entity.getCityId() != null, "b.city_id", entity.getCityId())
                .eq(entity.getDistrictId() != null, "b.district_id", entity.getDistrictId())
                .like(!StrUtil.isEmpty(entity.getEntName()), "a.ent_name", entity.getEntName())
                .like(!StrUtil.isEmpty(entity.getProjectName()), "a.project_name", entity.getProjectName())
                .like(!StrUtil.isEmpty(entity.getLicense()), "b.license", entity.getLicense())
                .like(!StrUtil.isEmpty(entity.getProjectName()), "a.project_name", entity.getEntName())
                .like(!StrUtil.isEmpty(entity.getProjectNo()), "a.project_no", entity.getProjectNo())
                .in(entity.getYearList() != null && !entity.getYearList().isEmpty(),
                        "a.project_year", entity.getYearList())
                .orderByDesc("a.id");

        SysUser user = SecurityUtils.getLoginUser().getUser();
        switch (user.getUserType()) {
            case ADMIN:
                queryWrapper.eq("project_owner", 1);
                break;
            case ENT_ADMIN:
                queryWrapper.eq("project_owner", 1).eq("ent_id", user.getScopeId());
                break;
            case ENT_ADMIN_TECH:
                queryWrapper.eq("project_owner", 2).eq("ent_id", user.getScopeId());
                break;
            case ENT_ADMIN_FIN:
                queryWrapper.eq("project_owner", 3).eq("ent_id", user.getScopeId());
                break;
            case ENT_TECH:
                queryWrapper.eq("project_owner", 2).eq("ent_id", user.getScopeId()).eq("user_id", user.getUserId());
                break;
            case ENT_FIN:
                queryWrapper.eq("project_owner", 3).eq("ent_id", user.getScopeId()).eq("user_id", user.getUserId());
                break;
            default:
                break;
        }

        Page<Project> page = baseMapper.selectPage(PageUtils.initPage(), queryWrapper);

        Page<ProjectListVO> res = new Page<ProjectListVO>();
        BeanUtil.copyProperties(page, res);
        if (!CollectionUtil.isEmpty(page.getRecords())) {
            List<ProjectListVO> list = new ArrayList<>();
            for (Project p : page.getRecords()) {
                ProjectListVO vo = BeanUtil.copyProperties(p, ProjectListVO.class);
                vo.setEntCompRate(getProject(p, 1).getCompRate());
                vo.setTechCompRate(getProject(p, 2).getCompRate());
                vo.setFinCompRate(getProject(p, 3).getCompRate());

                Long attachCnt = attachService.lambdaQuery()
                        .eq(Attach::getAttachType, AttachTypeEnum.PROJECT.name())
                        .eq(Attach::getDataId, p.getId()).count();
                vo.setAttachCnt(attachCnt);
                list.add(vo);
            }
            res.setRecords(list);
        }
        return res;
    }

    @Override
    public Page<Project> selectReportProject(ProjectQueryVO entity) {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>()
                .eq(entity.getProvinceId() != null, "b.province_id", entity.getProvinceId())
                .eq(entity.getCityId() != null, "b.city_id", entity.getCityId())
                .eq(entity.getDistrictId() != null, "b.district_id", entity.getDistrictId())
                .like(!StrUtil.isEmpty(entity.getEntName()), "a.ent_name", entity.getEntName())
                .like(!StrUtil.isEmpty(entity.getLicense()), "b.license", entity.getLicense())
                .like(!StrUtil.isEmpty(entity.getProjectName()), "a.project_name", entity.getEntName())
                .like(!StrUtil.isEmpty(entity.getProjectNo()), "a.project_no", entity.getProjectNo())
                .in(entity.getYearList() != null && !entity.getYearList().isEmpty(),
                        "a.project_year", entity.getYearList())
                .eq("a.report_flag", 1)
                .orderByDesc("a.id");
        SysUser user = SecurityUtils.getLoginUser().getUser();
        switch (user.getUserType()) {

            case ENT_ADMIN:
            case ENT_ADMIN_TECH:
            case ENT_ADMIN_FIN:
                queryWrapper.eq("a.project_owner", 3).eq("a.ent_id", user.getScopeId());
                break;
            case ENT_TECH:
                queryWrapper.eq("a.project_owner", 2).eq("a.ent_id", user.getScopeId()).eq("user_id", user.getUserId());
                break;
            case ENT_FIN:
                queryWrapper.eq("a.project_owner", 3).eq("a.ent_id", user.getScopeId()).eq("user_id", user.getUserId());
                break;
            case ADMIN:
                queryWrapper.eq("a.project_owner", 3);
                break;
            case GOV_PROV:
                queryWrapper.eq("a.project_owner", 3).eq("b.province_id", user.getScopeId());
                break;
            case GOV_CITY:
                queryWrapper.eq("a.project_owner", 3).eq("b.city_id", user.getScopeId());
                break;
            case GOV_DISTRI:
                queryWrapper.eq("a.project_owner", 3).eq("b.district_id", user.getScopeId());
                break;
            default:
                break;
        }

        Page<Project> page = baseMapper.selectPage(PageUtils.initPage(), queryWrapper);

        if (!CollectionUtil.isEmpty(page.getRecords())) {

            for (Project p : page.getRecords()) {
                Long attachCnt = attachService.lambdaQuery()
                        .eq(Attach::getAttachType, AttachTypeEnum.PROJECT.name())
                        .eq(Attach::getDataId, p.getId()).count();
                p.setAttachCnt(attachCnt);
            }
        }
        return page;
    }

    /**
     * 根据对应项目找到相关财务、技术或企业自填项目
     */
    @Override
    public Project getProject(Project oriProject, Integer projectOwner) {
        if (projectOwner == oriProject.getProjectOwner()) {
            Project project = redisCache.getCacheObject("project-draft:" + oriProject.getId());
            if (project != null) {
                return project;
            }
            oriProject.setProjectLogList(projectLogService.lambdaQuery().eq(ProjectLog::getProjectId, oriProject.getId()).list());
            return oriProject;
        } else {
//			QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>()
//					.and(wrapper -> wrapper.eq("project_ref_id", oriProject.getProjectRefId()).or().eq("id", oriProject.getProjectRefId()))
//					.eq("project_owner", projectOwner);

            QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>()
//					.eq(oriProject.getProjectRefId()!=null,"project_ref_id", oriProject.getProjectRefId())
//					.eq(oriProject.getProjectRefId()==null, "project_ref_id",oriProject.getId())
                    .eq("project_owner", projectOwner);

            if (oriProject.getProjectRefId() != null) {
                queryWrapper.and(wrapper -> wrapper.eq("project_ref_id", oriProject.getProjectRefId()).or().eq("id", oriProject.getProjectRefId()));
            } else {
                queryWrapper.eq("project_ref_id", oriProject.getId());
            }
            Project pro = this.getOne(queryWrapper);
            if (pro != null) {
                pro.setProjectLogList(projectLogService.lambdaQuery().eq(ProjectLog::getProjectId, oriProject.getId()).list());
            }
            return pro;
        }
    }

    @Override
    public ProjectDetailVO getProject(Integer projectId) {
        Project project = this.getById(projectId);
        if (project == null)
            return null;
        else {
            ProjectDetailVO vo = new ProjectDetailVO();
            vo.setEntProject(getProject(project, 1));
            vo.setTechProject(getProject(project, 2));
            vo.setFinProject(getProject(project, 3));
            try {
                vo.setTechUser(userService.getById(vo.getTechProject().getUserId()).getUserName());
                vo.setFinUser(userService.getById(vo.getFinProject().getUserId()).getUserName());
            } catch (Exception e) {
            }
            return vo;
        }
    }

    @Override
    @Transactional
    public Boolean saveProject(ProjectAddVO project) {
        SysUser user = SecurityUtils.getLoginUser().getUser();

        //log.info("user.getScopeId:{}",user.getScopeId());
        Enterprise enterprise = enterpriseService.getById(user.getScopeId());
        String entName = enterprise != null ? enterprise.getEntName() : null;


        Project entProject = BeanUtil.copyProperties(project, Project.class);
        Project techProject = BeanUtil.copyProperties(project, Project.class);
        Project finProject = BeanUtil.copyProperties(project, Project.class);

        entProject.setUserId(user.getUserId());
        entProject.setProjectOwner(1);
        entProject.setEntName(entName);

        this.save(entProject);

        techProject.setUserId(project.getTechUserId());
        techProject.setProjectOwner(2);
        techProject.setProjectRefId(entProject.getId());
        techProject.setEntName(entName);

        this.save(techProject);

        finProject.setUserId(project.getFinUserId());
        finProject.setProjectOwner(3);
        finProject.setProjectRefId(entProject.getId());
        finProject.setEntName(entName);

        this.save(finProject);

        projectLogService.saveLog(entProject, "项目录入");
        projectLogService.saveLog(techProject, "项目录入");
        projectLogService.saveLog(finProject, "项目录入");

        notifyService.asignProjectMsg(project);

        return true;
    }

    @Override
    public boolean syncProject(Integer id, Integer projectOwner) {
        Project oriProject = this.getById(id);
        if (oriProject == null) throw new ServiceException("项目不存在");
        Project target = this.getProject(oriProject, projectOwner);
        Integer targetId = target.getId();

        Project newPro = BeanUtil.copyProperties(oriProject, Project.class, "projectOwner", "projectRefId", "userId");
        newPro.setId(targetId);

        String projectFrom = "企业";
        if (oriProject.getProjectOwner() == 2) projectFrom = "技术";
        else if (oriProject.getProjectOwner() == 3) projectFrom = "财务";
        projectLogService.saveLog(targetId, "从[" + projectFrom + "]同步信息");
        // 2023-07-05 优化：当企业没有数据或数据空缺时，可提示，无可同步的信息，这里提示成功，还以为是有数据可以同步
        // 因为所有字段都是必填的,随便判断一个必填字段是否为空即可知晓有无数据
        if (StringUtils.isEmpty(oriProject.getAddress())) {
            return false;
        }
        return this.saveOrUpdate(newPro);
    }

    /**
     * 项目申报
     */
    @Override
    public boolean report(Integer id) {
        Project pro = this.getById(id);
        if (pro == null) throw new ServiceException("项目不存在");
//		this.lambdaUpdate().set(Project::getReportFlag, 1).set(Project::getReportState, 2).eq(Project::getId, id).update();
//		this.lambdaUpdate().set(Project::getReportState, 2).eq(Project::getId, oriProject.getProjectRefId()).or().eq(Project::getProjectRefId, oriProject.getProjectRefId()).update();
//		

        Project entPro = this.getProject(pro, 1);
        Project techPro = this.getProject(pro, 2);
        Project fincPro = this.getProject(pro, 3);
        //更新为待申报
        this.lambdaUpdate().set(Project::getReportState, 2).set(Project::getReportFlag, 1).in(Project::getId, Arrays.asList(entPro.getId(), techPro.getId(), fincPro.getId())).update();
        projectLogService.saveLog(id, "提交申报");

        notifyService.reportProjectMsg(id);
        return true;
    }

    @Override
    public IndexRptVO rptProject() {

        QueryWrapper<Enterprise> queryWrapper = new QueryWrapper<Enterprise>().eq("a.project_owner", 1);
        ;

        SysUser user = SecurityUtils.getLoginUser().getUser();
        switch (user.getUserType()) {
//			case ADMIN:
//				break;
            case GOV_PROV:
                queryWrapper.eq("b.province_id", user.getScopeId());
                break;
            case GOV_CITY:
                queryWrapper.eq("b.city_id", user.getScopeId());
                break;
            case GOV_DISTRI:
                queryWrapper.eq("b.district_id", user.getScopeId());
                break;

            case ENT_ADMIN:
            case ENT_ADMIN_TECH:
            case ENT_ADMIN_FIN:
            case ENT_TECH:
            case ENT_FIN:
                queryWrapper.eq("a.ent_id", user.getScopeId());
                break;

            default:
                break;
        }
        return baseMapper.rptProject(queryWrapper);
    }

    @Override
    public boolean cancel(Integer[] ids) {
        for (Integer projectId : ids) {
            Project pro = this.getById(projectId);

            Project entPro = this.getProject(pro, 1);
            Project techPro = this.getProject(pro, 2);
            Project fincPro = this.getProject(pro, 3);
            //更新为待申报
            this.lambdaUpdate().set(Project::getReportState, 3).set(Project::getReportFlag, 0).in(Project::getId, Arrays.asList(entPro.getId(), techPro.getId(), fincPro.getId())).update();
        }
        return true;
    }

    @Override
    public boolean remove(Integer[] ids) {
        for (Integer projectId : ids) {
            Project pro = this.getById(projectId);

            Project entPro = this.getProject(pro, 1);
            Project techPro = this.getProject(pro, 2);
            Project fincPro = this.getProject(pro, 3);
            //更新为待申报
            this.lambdaUpdate().in(Project::getId, Arrays.asList(entPro.getId(), techPro.getId(), fincPro.getId())).remove();
        }
        return true;
    }
}
