package com.ruoyi.web.report.service.impl;

import com.ruoyi.web.report.domain.design.ReportDesignDetailVo;
import com.ruoyi.web.report.domain.design.ReportDesignSaveBo;
import com.ruoyi.web.report.domain.design.ReportFieldDesign;
import com.ruoyi.web.report.mapper.ReportDesignMapper;
import com.ruoyi.web.report.service.IReportDesignService;
import com.ruoyi.web.report.service.support.ReportSqlSecurityValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 报表设计配置服务实现。
 *
 * <p>该服务负责将开发端配置一次性写入各元数据表，
 * 并在保存前进行必要的安全和空值兜底处理。</p>
 */
@Service
public class ReportDesignServiceImpl implements IReportDesignService {

    @Autowired
    private ReportDesignMapper reportDesignMapper;

    @Autowired
    private ReportSqlSecurityValidator sqlSecurityValidator;

    @Override
    public ReportDesignDetailVo getDesign(Long reportId) {
        ReportDesignDetailVo vo = new ReportDesignDetailVo();
        vo.setFields(reportDesignMapper.selectFieldsByReportId(reportId));
        vo.setJoins(reportDesignMapper.selectJoinsByReportId(reportId));
        vo.setCustomSql(reportDesignMapper.selectCustomSqlByReportId(reportId));
        vo.setAggregatePolicy(reportDesignMapper.selectAggregatePolicyByReportId(reportId));
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveDesign(Long reportId, ReportDesignSaveBo saveBo) {
        if (saveBo == null) {
            throw new IllegalArgumentException("保存参数不能为空。");
        }
        // 先清后写，保证配置数据原子性和幂等性。
        reportDesignMapper.deleteFieldsByReportId(reportId);
        reportDesignMapper.deleteJoinsByReportId(reportId);
        reportDesignMapper.deleteCustomSqlByReportId(reportId);
        reportDesignMapper.deleteAggregatePolicyByReportId(reportId);

        int affected = 0;
        if (saveBo.getFields() != null && !saveBo.getFields().isEmpty()) {
            normalizeFieldValueType(saveBo);
            affected += reportDesignMapper.insertFieldBatch(reportId, saveBo.getFields());
        }
        if (saveBo.getJoins() != null && !saveBo.getJoins().isEmpty()) {
            affected += reportDesignMapper.insertJoinBatch(reportId, saveBo.getJoins());
        }
        if (saveBo.getCustomSql() != null && !saveBo.getCustomSql().trim().isEmpty()) {
            // 保存前做基础安全校验，防止危险语句入库。
            sqlSecurityValidator.validateCustomSelectSql(saveBo.getCustomSql());
            affected += reportDesignMapper.insertCustomSql(reportId, saveBo.getCustomSql().trim());
        }
        if (saveBo.getAggregatePolicy() != null) {
            affected += reportDesignMapper.insertAggregatePolicy(reportId, saveBo.getAggregatePolicy());
        }
        // toAjax 只需判断 >0，这里兜底返回 1 表示保存流程执行成功。
        return affected <= 0 ? 1 : affected;
    }

    /**
     * 统一兜底字段值类型，防止前端漏传导致 value_type 为空。
     */
    private void normalizeFieldValueType(ReportDesignSaveBo saveBo) {
        for (ReportFieldDesign field : saveBo.getFields()) {
            if (field == null) {
                continue;
            }
            String valueType = field.getValueType();
            if (valueType == null || valueType.trim().isEmpty()) {
                field.setValueType("STRING");
            } else {
                field.setValueType(valueType.trim().toUpperCase());
            }
        }
    }
}
