
package com.lideeyunji.core.framework.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lideeyunji.core.framework.config.aspect.enhancereport.LideeYunJiReportEnhance;
import com.lideeyunji.core.framework.config.aspect.enhancereport.enums.RefreshPluginEnums;
import com.lideeyunji.core.framework.entity.ReportEntity;
import com.lideeyunji.core.framework.entity.ReportFieldEntity;
import com.lideeyunji.core.framework.mapper.ReportFieldMapper;
import com.lideeyunji.core.framework.mapper.ReportMapper;
import com.lideeyunji.core.framework.params.PageReportParam;
import com.lideeyunji.core.framework.params.ReportAddOrUpdateParam;
import com.lideeyunji.core.framework.params.vo.ReportConfigVo;
import com.lideeyunji.core.framework.params.vo.ReportDeletedVo;
import com.lideeyunji.core.framework.params.vo.ReportFieldVo;
import com.lideeyunji.core.framework.params.vo.ReportVo;
import com.lideeyunji.core.framework.params.vo.webconfigreport.WebConfigReportVo;
import com.lideeyunji.core.framework.params.vo.webconfigreport.WebConfigVo;
import com.lideeyunji.core.framework.service.IBatchService;
import com.lideeyunji.core.framework.service.IReportService;
import com.lideeyunji.core.framework.utils.Func;
import com.lideeyunji.tool.framework.exception.lideeYunJiException;
import com.lideeyunji.tool.framework.yunji.adapter.IlideeYunjiAdapter;
import com.lideeyunji.tool.framework.yunji.annotation.lideeYunjiCache;
import com.lideeyunji.tool.framework.yunji.constant.lideeYunjiCodeConstant;
import com.lideeyunji.tool.framework.yunji.constant.lideeRedisConstants;
import com.lideeyunji.tool.framework.yunji.enums.AuthTypeEnum;
import com.lideeyunji.tool.framework.yunji.enums.TableType2Enum;
import com.lideeyunji.tool.framework.yunji.enums.YNEnum;
import com.lideeyunji.tool.framework.yunji.model.lideeYunjiDict;
import com.lideeyunji.tool.framework.yunji.params.lideeYunJiDictParam;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
import com.lideeyunji.tool.framework.yunji.utils.lideeYunJiUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 数据报表相关
 */
@Service
public class ReportServiceImpl extends ServiceImpl<ReportMapper, ReportEntity> implements IReportService {

    @Autowired
    private ReportFieldMapper reportFieldMapper;

    @Autowired
    private IBatchService batchService;

    @Autowired
    private IlideeYunjiAdapter lideeYunJiAdapter;

    private ReportServiceImpl getSelf() {
        return SpringUtil.getBean(getClass());
    }


    //获取认证类型

    @Override
    public AuthTypeEnum getAuthType(String reportCode) {
        ReportEntity reportEntity = this.getReportEntityByCode(reportCode);
        String dataConfig = reportEntity.getDataConfig();
        if (FuncBase.isEmpty(dataConfig)) {
            return null;
        }
        List<String> dataConfigList = FuncBase.toStrList(dataConfig);
        for (String type : dataConfigList) {
            AuthTypeEnum authTypeEnum = AuthTypeEnum.getByType(type);
            if (Func.isNotEmpty(authTypeEnum)) {
                return authTypeEnum;
            }
        }
        return null;

    }


    //根据id获取
    @Override
    public ReportEntity getReportEntityById(Long reportId) {
        ReportEntity entity = baseMapper.getById(reportId);
        if (FuncBase.isEmpty(entity)) {
            throw new lideeYunJiException("数据统计表不存在");
        }
        return entity;
    }

    //根据code获取
    @Override
    public ReportEntity getReportEntityByCode(String reportCode) {
        ReportEntity entity = baseMapper.getByCode(reportCode);
        if (FuncBase.isEmpty(entity)) {
            throw new lideeYunJiException("数据报表不存在");
        }
        return entity;
    }


    //保存数据报表
    @lideeYunjiCache(cacheNames = lideeRedisConstants.REDIS_REPORT+":*", delCache = true)//全清
    @Override
    @DSTransactional(rollbackFor = Exception.class)
    public Long saveReportConfig(ReportAddOrUpdateParam param) {
        long formId = IdWorker.getId();
        this.saveOrupdateReportConfig(param, formId);
        return formId;
    }

    //修改数据报表
    @Override
    @DSTransactional(rollbackFor = Exception.class)
    @lideeYunjiCache(cacheNames = lideeRedisConstants.REDIS_REPORT+":*", delCache = true)//全清
    public void updateReportConfig(ReportAddOrUpdateParam param) {
        this.saveOrupdateReportConfig(param, param.getReport().getId());
    }

    //删除 - 表单开发
    @Override
    @DSTransactional(rollbackFor = Exception.class)
    @lideeYunjiCache(cacheNames = lideeRedisConstants.REDIS_REPORT+":*", delCache = true)//全清
    public void deleteReportConfig(List<Long> reportIdList) {
        reportIdList.stream().forEach(reportId -> {
            ReportEntity reportEntity = baseMapper.selectById(reportId);
            if (FuncBase.isEmpty(reportEntity)) {
                return;
            }

            //1.删除主表
            baseMapper.deleteById(reportId);
            //2.删除属性表
            QueryWrapper<ReportFieldEntity> fieldWrapper = new QueryWrapper();
            fieldWrapper.eq("report_id", reportId);
            reportFieldMapper.delete(fieldWrapper);

            LideeYunJiReportEnhance.refreshPlugin(RefreshPluginEnums.DEL, reportEntity.getReportCode(),reportEntity.getJavaConfig());
        });

    }

    /**
     * 获取详情
     *
     * @param reportId
     * @return
     */
    @Override
    public ReportConfigVo getReportConfig(Long reportId) {
        ReportConfigVo resultVo = new ReportConfigVo();

        ReportServiceImpl reportService = getSelf();
        //表单配置
        ReportEntity reportEntity = reportService.getReportEntityById(reportId);
        resultVo.setReport(reportEntity);

        //字段信息
        List<ReportFieldEntity> fieldEntityList = reportFieldMapper.getByDbReportId(reportId);
        resultVo.setFieldList(fieldEntityList);

        return resultVo;
    }


    //分页 - 表单开发
    @Override
    public IPage<ReportEntity> getPageReportConfig(PageReportParam param, Page page) {
        LambdaQueryWrapper<ReportEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FuncBase.isNotEmpty(param.getGroupReportId()), ReportEntity::getGroupReportId, param.getGroupReportId());
        wrapper.like(FuncBase.isNotEmpty(param.getReportName()), ReportEntity::getReportName, param.getReportName());
        wrapper.like(FuncBase.isNotEmpty(param.getReportCode()), ReportEntity::getReportCode, param.getReportCode());
        wrapper.like(FuncBase.isNotEmpty(param.getJavaConfig()), ReportEntity::getJavaConfig, param.getJavaConfig());
        wrapper.orderByDesc(ReportEntity::getId);
        IPage<ReportEntity> pages = baseMapper.selectPage(page, wrapper);
        return pages;
    }

    //前端配置
    @Override
    public WebConfigVo getWebConfig(String reportCode) {
        ReportEntity reportEntity = baseMapper.getByCode(reportCode);

        //报表基本配置
        ReportConfigVo reportConfig = this.getReportConfig(reportEntity.getId());

        //转为一条返回给前端
        List<ReportFieldEntity> fieldList = reportConfig.getFieldList();//字段列表

        //封装结果返回
        WebConfigVo webConfigVo = new WebConfigVo();
        webConfigVo.setFieldList(fieldList);
        webConfigVo.setReportVo(BeanUtil.copyProperties(reportConfig.getReport(), WebConfigReportVo.class));
        return webConfigVo;
    }

    //回显字典
    @Override
    public void formatDataList(Long reportId, List<Map<String, Object>> records) {
        //获取字典code
        LambdaQueryWrapper<ReportFieldEntity> fieldWrapper = new LambdaQueryWrapper<>();
        fieldWrapper.isNotNull(ReportFieldEntity::getDictCode);
        fieldWrapper.eq(ReportFieldEntity::getReportId,reportId);
        List<ReportFieldEntity> fieldEntityList = reportFieldMapper.selectList(fieldWrapper);
        if (Func.isEmpty(fieldEntityList)) {
            return;
        }
        //封装为map
        Map<String, Map<String, String>> field2DictMap = new HashMap<>();
        for (ReportFieldEntity fieldEntity : fieldEntityList) {
            String fieldCode = fieldEntity.getFieldCode();
            String dictCode = fieldEntity.getDictCode();
            if (Func.isEmpty(dictCode)) {
                continue;
            }

            lideeYunJiDictParam param = new lideeYunJiDictParam();
            param.setDictCodeList(FuncBase.toStrList(dictCode));
            List<lideeYunjiDict> dictList = lideeYunJiAdapter.getDictList(param);
            if (Func.isEmpty(dictList)) {
                continue;
            }
            lideeYunjiDict lideeYunjiDict = dictList.get(0);
            List<lideeYunjiDict.DictData> dataList = lideeYunjiDict.getDataList();
            if (Func.isEmpty(dataList)) {
                continue;
            }
            Map<String, String> dictDataMap = new HashMap<>();
            for (lideeYunjiDict.DictData dictData : dataList) {
                String label = dictData.getLabel();
                String val = dictData.getVal();
                dictDataMap.put(val, label);
            }
            field2DictMap.put(fieldCode, dictDataMap);
        }
        //遍历数据
        for (Map<String, Object> dataMap : records) {
            // 转换并格式化所有值
            Map<String, String> formattedMap = dataMap.entrySet().stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> lideeYunJiUtils.formatDate(entry.getValue())
                    ));

            // 使用格式化后的映射替换原始映射
            dataMap.clear();
            dataMap.putAll(formattedMap);


            Set<Map.Entry<String, Map<String, String>>> entries = field2DictMap.entrySet();
            Iterator<Map.Entry<String, Map<String, String>>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Map<String, String>> entity = iterator.next();

                String fieldCode = entity.getKey();
                String fieldVal = Func.getMap2Str(dataMap, fieldCode);

                Map<String, String> dictMap = entity.getValue();
                if (Func.isEmpty(fieldVal) || Func.isEmpty(dictMap)) {//没有值
                    continue;
                }
                String dictLabel = dictMap.get(fieldVal);
                if(Func.isEmpty(dictLabel)){
                    continue;
                }
                dataMap.put(fieldCode,dictLabel);

            }


        }


    }

    //复制
    @Override
    public void copy(String reportCode, String newReportCode){
        long reportId = IdWorker.getId();
        //复制主表
        ReportEntity entity = baseMapper.getByCode(reportCode);
        ReportVo reportVo = BeanUtil.copyProperties(entity, ReportVo.class);
        reportVo.setId(null);
        reportVo.setReportCode(newReportCode);
        reportVo.setReportName(reportVo.getReportName() + "_copy");
        String oldEnhance = entity.getJavaConfig();
        String newEnhance;
        if (oldEnhance.contains(lideeYunjiCodeConstant.DOT)) {
            // class方式
            newEnhance = Func.copyClassEnhance(TableType2Enum.REPORT.getType(), oldEnhance, newReportCode);
        }else {
            // spring方式
            newEnhance = Func.copySpringEnhance(TableType2Enum.REPORT.getType(), oldEnhance, newReportCode);
        }
        reportVo.setJavaConfig(newEnhance);

        //字段
        List<ReportFieldEntity> fieldEntityList = reportFieldMapper.getByDbReportId(entity.getId());
        List<ReportFieldVo> fieldVoList = Func.copyReportFieldList(fieldEntityList, ReportFieldVo.class);

        ReportAddOrUpdateParam param=new ReportAddOrUpdateParam();
        param.setFieldList(fieldVoList);
        param.setReport(reportVo);
        this.saveOrupdateReportConfig(param,reportId);

    }



    //新增 或 修改
    private void saveOrupdateReportConfig(ReportAddOrUpdateParam param, Long reportId) {
        //1.保存主表
        this.saveOrUpdateReport(reportId, param.getReport());

        ReportDeletedVo delIdVo = param.getDelIdVo();
        if (Func.isEmpty(delIdVo)) {
            delIdVo = new ReportDeletedVo();
        }

        //2.保存字段属性
        this.saveOrUpdateReportField(reportId, param.getFieldList(), delIdVo.getFieldList());
    }

    //数据报表-主表
    private void saveOrUpdateReport(long reportId, ReportVo vo) {
        ReportEntity entity = new ReportEntity();
        entity.setId(reportId);
        entity.setReportName(vo.getReportName());
        entity.setReportCode(vo.getReportCode());
        entity.setGroupReportId(vo.getGroupReportId());
        entity.setJavaConfig(vo.getJavaConfig());
        entity.setDataConfig(vo.getDataConfig());
        entity.setTableConfig(vo.getTableConfig());
        entity.setUpdateTime(LocalDateTime.now());
        entity.setDataSourcesConfig(vo.getDataSourcesConfig());//表视图数据来源
        entity.setDataSourcesCode(vo.getDataSourcesCode());
        if (FuncBase.isEmpty(vo.getId())) {//新增
            baseMapper.insert(entity);
            return;
        }
        baseMapper.updateById(entity);
    }

    //数据报表-字段
    private void saveOrUpdateReportField(long reportId, List<ReportFieldVo> fieldList, List<Long> delIdList) {
        if (Func.isNotEmpty(delIdList)) {
            reportFieldMapper.deleteBatchIds(delIdList);//删除
        }

        List<ReportFieldEntity> addList = new ArrayList<>();
        List<ReportFieldEntity> updateList = new ArrayList<>();
        Integer sortNum = 0;
        for (ReportFieldVo vo : fieldList) {
            Long id = vo.getId();
            id = Func.isNotEmpty(id) ? id : IdWorker.getId();

            ReportFieldEntity entity = new ReportFieldEntity();
            entity.setId(id);
            entity.setReportId(reportId);
            entity.setFieldCode(vo.getFieldCode());
            entity.setFieldName(vo.getFieldName());
            entity.setFieldType(vo.getFieldType());
            entity.setSortNum(++sortNum);
            entity.setQueryIsDb(vo.getQueryIsDb());
            entity.setQueryIsWeb(vo.getQueryIsWeb());
            entity.setQueryMode(vo.getQueryMode());
            entity.setDictCode(vo.getDictCode());
            entity.setIsExport(vo.getIsExport());
            entity.setIsShowSort(vo.getIsShowSort());
            entity.setIsDimension(vo.getIsDimension());
            entity.setIsHideDimension(vo.getIsHideDimension());
            entity.setIsFixedColumn(vo.getIsFixedColumn());   //2026-02-10  新增
            entity.setFixedColumnValue(vo.getFixedColumnValue());  //2026-02-10  新增
            entity.setIsHideCol(vo.getIsHideCol());  //2026.2.10  新增
            entity.setSearchDefaultValue(vo.getSearchDefaultValue());
            entity.setWidth(vo.getWidth());
            entity.setIsDynamicGroup(vo.getIsDynamicGroup());
            entity.setHasChildren(vo.getHasChildren());
            entity.setParentFieldCode(vo.getParentFieldCode());
            entity.setParentFieldName(vo.getParentFieldName());
            entity.setIsAmount(vo.getIsAmount());
            entity.setLabelI18n(vo.getLabelI18n());
            if (FuncBase.isEmpty(vo.getId())) {//新增
                addList.add(entity);
            } else if (Func.equals(vo.getIsModify(), YNEnum.Y.getCode())) {//如果是N的时候，不修改
                updateList.add(entity);
            }

        }

        if (Func.isNotEmpty(addList)) {//新增
            batchService.saveBatch(addList, reportFieldMapper, ReportFieldMapper.class, ReportFieldEntity.class);
        }

        if (Func.isNotEmpty(updateList)) {
            batchService.updateBatchById(updateList, reportFieldMapper, ReportFieldMapper.class, ReportFieldEntity.class);
        }

    }


}
