package com.xjrsoft.module.report.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.toolkit.MPJWrappers;
import com.xjrsoft.common.enums.MenuType;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.report.dto.AddReportReleaseDto;
import com.xjrsoft.module.report.dto.ReportReleasePageDto;
import com.xjrsoft.module.report.dto.UpdateReportReleaseDto;
import com.xjrsoft.module.report.entity.ProfessionalReport;
import com.xjrsoft.module.report.entity.Report;
import com.xjrsoft.module.report.entity.ReportRelation;
import com.xjrsoft.module.report.mapper.ProfessionalReportMapper;
import com.xjrsoft.module.report.mapper.ReportMapper;
import com.xjrsoft.module.report.mapper.ReportRelationMapper;
import com.xjrsoft.module.report.service.IReportRelationService;
import com.xjrsoft.module.report.vo.ReportReleaseInfoVo;
import com.xjrsoft.module.report.vo.ReportReleasePageVo;
import com.xjrsoft.module.system.entity.Menu;
import com.xjrsoft.module.system.mapper.MenuMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 报表菜单关联关系表 服务实现类
 * </p>
 *
 * @author tzx
 * @since 2022-05-23
 */
@Service
@AllArgsConstructor
public class ReportRelationServiceImpl extends ServiceImpl<ReportRelationMapper, ReportRelation> implements IReportRelationService {

    private final ReportRelationMapper reportRelationMapper;

    private final ProfessionalReportMapper professionalReportMapper;

    private final ReportMapper reportMapper;

    private final MenuMapper menuMapper;

    @Override
    public PageOutput<ReportReleasePageVo>  releasePage(ReportReleasePageDto dto) {
        //ureport数据
        List<ReportReleasePageVo> reportList = reportRelationMapper.selectJoinList(ReportReleasePageVo.class,
                MPJWrappers.<ReportRelation>lambdaJoin()
                        .like(StrUtil.isNotBlank(dto.getKeyword()), Report::getName, dto.getKeyword())
                        .select(ReportRelation::getId)
                        .select(ReportRelation.class, x -> VoToColumnUtil.fieldsToColumns(ReportRelation.class).contains(x.getProperty()))
                        .selectAs(Menu::getTitle, ReportReleasePageVo::getTitle)
                        .selectAs(Menu::getCode, ReportReleasePageVo::getCode)
                        .selectAs(Menu::getParentId, ReportReleasePageVo::getParentId)
                        .selectAs(Report::getName, ReportReleasePageVo::getReportName)
                        .selectAs(Menu::getRemark, ReportReleasePageVo::getRemark)
                        .leftJoin(Menu.class, Menu::getId, ReportRelation::getMenuId)
                        .leftJoin(Report.class, Report::getId, ReportRelation::getReportId)
                        .orderByDesc(StrUtil.isBlank(dto.getField()), Menu::getCreateDate));
        //葡萄城数据
        List<ReportReleasePageVo> professionalReportList = reportRelationMapper.selectJoinList(ReportReleasePageVo.class,
                MPJWrappers.<ReportRelation>lambdaJoin()
                        .like(StrUtil.isNotBlank(dto.getKeyword()), ProfessionalReport::getName, dto.getKeyword())
                        .select(ReportRelation::getId)
                        .select(ReportRelation.class, x -> VoToColumnUtil.fieldsToColumns(ReportRelation.class).contains(x.getProperty()))
                        .selectAs(Menu::getTitle, ReportReleasePageVo::getTitle)
                        .selectAs(Menu::getCode, ReportReleasePageVo::getCode)
                        .selectAs(Menu::getParentId, ReportReleasePageVo::getParentId)
                        .selectAs(ProfessionalReport::getName, ReportReleasePageVo::getReportName)
                        .selectAs(Menu::getRemark, ReportReleasePageVo::getRemark)
                        .leftJoin(Menu.class, Menu::getId, ReportRelation::getMenuId)
                        .leftJoin(ProfessionalReport.class, ProfessionalReport::getId, ReportRelation::getReportId)
                        .orderByDesc(StrUtil.isBlank(dto.getField()), Menu::getCreateDate));

        if (professionalReportList.size() > 0){
            reportList.addAll(professionalReportList);
        }
        Set<Long> parentIdList = reportList.stream().filter(vo -> vo.getParentId() != null && vo.getParentId() != 0L).map(ReportReleasePageVo::getParentId).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(parentIdList)) {
            // 设置parentName
            List<Menu> parentMenuList = menuMapper.selectList(Wrappers.<Menu>query().lambda()
                    .select(Menu::getId, Menu::getTitle).in(Menu::getId, parentIdList));
            for (ReportReleasePageVo pageVo : reportList) {
                for (Menu parentMenu : parentMenuList) {
                    if (parentMenu.getId().equals(pageVo.getParentId())) {
                        pageVo.setParentName(parentMenu.getTitle());
                    }
                }
            }
        }
        PageOutput<ReportReleasePageVo> output = new PageOutput<>();
        output.setCurrentPage(dto.getLimit());
        output.setPageSize(dto.getSize());
        output.setTotal(reportList.size());
        output.setList(reportList);

        return output;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(AddReportReleaseDto dto) {
        Menu menu = BeanUtil.toBean(dto, Menu.class);
        setMenuInfo(menu,dto.getDataType());
        menu.setName(dto.getTitle());
        if (dto.getDataType() == YesOrNoEnum.NO.getCode()){
            Report report = reportMapper.selectOne(Wrappers.<Report>query().lambda().select(Report::getName).eq(Report::getId, dto.getReportId()));
            if (report != null) {
                String reportName = report.getName();
                menu.setPath("/report/" + reportName.substring(0, reportName.indexOf(".")));
            }
        }else {
            menu.setPath("/activereport-home/" + dto.getReportId());
        }
        menuMapper.insert(menu);
        ReportRelation relation = new ReportRelation();
        relation.setMenuId(menu.getId());
        relation.setReportId(dto.getReportId());
        return this.save(relation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(UpdateReportReleaseDto dto) {

        Menu menu = BeanUtil.toBean(dto, Menu.class);
        menu.setId(dto.getMenuId());
        setMenuInfo(menu,dto.getDataType());
        menu.setName(dto.getTitle());
        if (dto.getDataType() == YesOrNoEnum.NO.getCode()){
            Report report = reportMapper.selectOne(Wrappers.<Report>query().lambda().select(Report::getName).eq(Report::getId, dto.getReportId()));
            if (report != null) {
                String reportName = report.getName();
                menu.setPath("/report/" + reportName.substring(0, reportName.indexOf(".")));
            }
        }else {
            menu.setPath("/activereport-home/" + dto.getReportId());
        }
        menuMapper.updateById(menu);
        ReportRelation relation = new ReportRelation();
        relation.setId(dto.getId());
        relation.setMenuId(dto.getMenuId());
        relation.setReportId(dto.getReportId());
        return this.updateById(relation);
    }

    @Override
    public ReportReleaseInfoVo info(Long id) {
        ReportRelation reportRelation = this.getById(id);
        ReportReleaseInfoVo infoVo = BeanUtil.toBean(reportRelation, ReportReleaseInfoVo.class);
        Menu menu = menuMapper.selectById(reportRelation.getMenuId());
        BeanUtil.copyProperties(menu, infoVo, true);
        return infoVo;
    }

    private void setMenuInfo(Menu menu,Integer dataType) {
        menu.setComponentType(YesOrNoEnum.YES.getCode());
        menu.setMenuType(MenuType.FUNCTION.getCode());
        if (dataType == YesOrNoEnum.NO.getCode()){
            menu.setComponent("report/template/index");
        }else {
            menu.setComponent("activereport/menu/index");
        }
        menu.setDisplay(YesOrNoEnum.YES.getCode());
        menu.setAllowDelete(YesOrNoEnum.YES.getCode());
        menu.setAllowModify(YesOrNoEnum.YES.getCode());
        menu.setOutLink(YesOrNoEnum.NO.getCode());
        menu.setKeepAlive(YesOrNoEnum.NO.getCode());
    }
}
