/*
 * 文 件 名:  CustomReportController
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  <描述>
 * 修 改 人:  lvwenbin
 * 修改时间:  2026/1/30
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.ruoyi.ems.controller;

import com.huashe.common.domain.AjaxResult;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.ems.domain.ReportDatasource;
import com.ruoyi.ems.domain.ReportField;
import com.ruoyi.ems.domain.ReportFieldCondition;
import com.ruoyi.ems.domain.ReportQueryConfig;
import com.ruoyi.ems.domain.ReportRelation;
import com.ruoyi.ems.domain.ReportTemplate;
import com.ruoyi.ems.model.ReportQueryResult;
import com.ruoyi.ems.service.ICustomReportService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 自定义报表Controller
 *
 * 提供动态SQL查询能力，支持：
 * 1. 数据源管理（配置可查询的表）
 * 2. 字段配置（配置可选字段和条件）
 * 3. 报表模板管理（保存/加载用户配置）
 * 4. 动态查询执行（根据配置生成SQL并执行）
 * 5. 数据导出（Excel导出）
 *
 * @author ruoyi
 * @date 2026-01-30
 */
@RestController
@RequestMapping("/report/custom")
@Api(value = "CustomReportController", description = "自定义报表接口")
public class CustomReportController extends BaseController {

    @Autowired
    private ICustomReportService customReportService;

    // ==================== 数据源管理 ====================

    /**
     * 查询所有可用的数据源
     */
    @RequiresPermissions("report:custom:list")
    @GetMapping("/datasource/list")
    @ApiOperation("查询数据源列表")
    public AjaxResult listDatasources(
        @ApiParam("分类筛选") @RequestParam(required = false) String category) {
        List<ReportDatasource> list = customReportService.selectDatasourceList(category);
        return success(list);
    }

    /**
     * 获取数据源详情（包含字段、条件、关联配置）
     */
    @RequiresPermissions("report:custom:list")
    @GetMapping("/datasource/{dsCode}")
    @ApiOperation("获取数据源详情")
    public AjaxResult getDatasourceDetail(
        @ApiParam("数据源编码") @PathVariable String dsCode) {
        ReportDatasource datasource = customReportService.selectDatasourceDetail(dsCode);
        if (datasource == null) {
            return error("数据源不存在");
        }
        return success(datasource);
    }

    /**
     * 获取数据源的字段列表
     */
    @RequiresPermissions("report:custom:list")
    @GetMapping("/datasource/{dsCode}/fields")
    @ApiOperation("获取数据源字段列表")
    public AjaxResult getDatasourceFields(
        @ApiParam("数据源编码") @PathVariable String dsCode) {
        List<ReportField> fields = customReportService.selectFieldsByDsCode(dsCode);
        return success(fields);
    }

    /**
     * 获取字段的可用条件
     */
    @RequiresPermissions("report:custom:list")
    @GetMapping("/datasource/{dsCode}/field/{fieldCode}/conditions")
    @ApiOperation("获取字段条件列表")
    public AjaxResult getFieldConditions(
        @ApiParam("数据源编码") @PathVariable String dsCode,
        @ApiParam("字段编码") @PathVariable String fieldCode) {
        List<ReportFieldCondition> conditions = customReportService.selectFieldConditions(dsCode, fieldCode);
        return success(conditions);
    }

    // ==================== 报表模板管理 ====================

    /**
     * 查询模板列表
     */
    @RequiresPermissions("report:custom:list")
    @GetMapping("/template/list")
    @ApiOperation("查询报表模板列表")
    public TableDataInfo listTemplates(ReportTemplate query) {
        startPage();
        // 设置当前用户ID，用于查询私有模板
        Long userId = SecurityUtils.getUserId();
        query.setUserId(userId);
        List<ReportTemplate> list = customReportService.selectTemplateList(query);
        return getDataTable(list);
    }

    /**
     * 获取模板详情
     */
    @RequiresPermissions("report:custom:list")
    @GetMapping("/template/{templateCode}")
    @ApiOperation("获取报表模板详情")
    public AjaxResult getTemplate(
        @ApiParam("模板编码") @PathVariable String templateCode) {
        ReportTemplate template = customReportService.selectTemplateByCode(templateCode);
        if (template == null) {
            return error("模板不存在");
        }
        return success(template);
    }

    /**
     * 保存模板
     */
    @RequiresPermissions("report:custom:add")
    @Log(title = "自定义报表模板", businessType = BusinessType.INSERT)
    @PostMapping("/template")
    @ApiOperation("保存报表模板")
    public AjaxResult saveTemplate(@RequestBody ReportTemplate template) {
        // 设置当前用户信息
        Long userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getUsername();
        template.setUserId(userId);
        template.setUserName(userName);
        template.setCreateBy(userName);

        int result = customReportService.saveTemplate(template);
        return result > 0 ? success("保存成功") : error("保存失败");
    }

    /**
     * 更新模板
     */
    @RequiresPermissions("report:custom:edit")
    @Log(title = "自定义报表模板", businessType = BusinessType.UPDATE)
    @PutMapping("/template")
    @ApiOperation("更新报表模板")
    public AjaxResult updateTemplate(@RequestBody ReportTemplate template) {
        // 检查权限（只能修改自己的模板或系统管理员）
        ReportTemplate existing = customReportService.selectTemplateByCode(template.getTemplateCode());
        if (existing == null) {
            return error("模板不存在");
        }
        Long userId = SecurityUtils.getUserId();
        if (existing.getIsSystem() != null && existing.getIsSystem() == 1) {
            return error("系统模板不可修改");
        }
        if (!userId.equals(existing.getUserId())) {
            return error("无权修改此模板");
        }

        template.setUpdateBy(SecurityUtils.getUsername());
        int result = customReportService.updateTemplate(template);
        return result > 0 ? success("更新成功") : error("更新失败");
    }

    /**
     * 删除模板
     */
    @RequiresPermissions("report:custom:remove")
    @Log(title = "自定义报表模板", businessType = BusinessType.DELETE)
    @DeleteMapping("/template/{templateCode}")
    @ApiOperation("删除报表模板")
    public AjaxResult deleteTemplate(
        @ApiParam("模板编码") @PathVariable String templateCode) {
        // 检查权限
        ReportTemplate existing = customReportService.selectTemplateByCode(templateCode);
        if (existing == null) {
            return error("模板不存在");
        }
        if (existing.getIsSystem() != null && existing.getIsSystem() == 1) {
            return error("系统模板不可删除");
        }
        Long userId = SecurityUtils.getUserId();
        if (!userId.equals(existing.getUserId())) {
            return error("无权删除此模板");
        }

        int result = customReportService.deleteTemplate(templateCode);
        return result > 0 ? success("删除成功") : error("删除失败");
    }

    // ==================== 动态查询执行 ====================

    /**
     * 执行报表查询
     */
    @RequiresPermissions("report:custom:query")
    @PostMapping("/query")
    @ApiOperation("执行报表查询")
    public AjaxResult executeQuery(@RequestBody ReportQueryConfig queryConfig) {
        try {
            // 参数校验
            if (queryConfig.getDsCode() == null && queryConfig.getTemplateCode() == null) {
                return error("请指定数据源或模板");
            }

            queryConfig.initDefaults();

            ReportQueryResult result = customReportService.executeQuery(queryConfig);
            return success(result);
        } catch (Exception e) {
            logger.error("执行报表查询异常", e);
            return error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 执行报表查询（基于模板）
     */
    @RequiresPermissions("report:custom:query")
    @PostMapping("/query/template/{templateCode}")
    @ApiOperation("基于模板执行查询")
    public AjaxResult executeQueryByTemplate(
        @ApiParam("模板编码") @PathVariable String templateCode,
        @ApiParam("参数值") @RequestBody(required = false) Map<String, Object> params) {
        try {
            ReportQueryConfig queryConfig = new ReportQueryConfig();
            queryConfig.setTemplateCode(templateCode);
            queryConfig.setParams(params);
            queryConfig.initDefaults();

            // 更新模板使用次数
            customReportService.incrementTemplateUseCount(templateCode);

            ReportQueryResult result = customReportService.executeQuery(queryConfig);
            return success(result);
        } catch (Exception e) {
            logger.error("执行模板查询异常", e);
            return error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 获取报表汇总数据
     */
    @RequiresPermissions("report:custom:query")
    @PostMapping("/summary")
    @ApiOperation("获取报表汇总数据")
    public AjaxResult getSummary(@RequestBody ReportQueryConfig queryConfig) {
        try {
            if (queryConfig.getDsCode() == null && queryConfig.getTemplateCode() == null) {
                return error("请指定数据源或模板");
            }

            Map<String, Object> summary = customReportService.executeSummaryQuery(queryConfig);
            return success(summary);
        } catch (Exception e) {
            logger.error("获取报表汇总异常", e);
            return error("查询失败: " + e.getMessage());
        }
    }

    // ==================== 数据导出 ====================

    /**
     * 导出报表数据
     */
    @RequiresPermissions("report:custom:export")
    @Log(title = "自定义报表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ApiOperation("导出报表数据")
    public void exportReport(HttpServletResponse response, @RequestBody ReportQueryConfig queryConfig) {
        try {
            queryConfig.setExportAll(true);
            queryConfig.initDefaults();

            // 执行查询获取全部数据
            ReportQueryResult result = customReportService.executeQuery(queryConfig);

            if (result.getCode() != 200) {
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":500,\"msg\":\"" + result.getMsg() + "\"}");
                return;
            }

            // 获取数据源信息用于文件名
            String dsCode = queryConfig.getDsCode();
            if (dsCode == null && queryConfig.getTemplateCode() != null) {
                ReportTemplate template = customReportService.selectTemplateByCode(queryConfig.getTemplateCode());
                if (template != null) {
                    dsCode = template.getDsCode();
                }
            }
            ReportDatasource datasource = customReportService.selectDatasourceByCode(dsCode);
            String dsName = datasource != null ? datasource.getDsName() : "报表";

            // 导出Excel
            customReportService.exportToExcel(response, result, dsName);
        } catch (Exception e) {
            logger.error("导出报表异常", e);
            try {
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":500,\"msg\":\"导出失败: " + e.getMessage() + "\"}");
            } catch (Exception ex) {
                logger.error("响应异常信息失败", ex);
            }
        }
    }

    // ==================== 配置管理(管理员) ====================

    /**
     * 新增数据源配置
     */
    @RequiresPermissions("report:config:add")
    @Log(title = "数据源配置", businessType = BusinessType.INSERT)
    @PostMapping("/datasource")
    @ApiOperation("新增数据源配置")
    public AjaxResult addDatasource(@RequestBody ReportDatasource datasource) {
        datasource.setCreateBy(SecurityUtils.getUsername());
        int result = customReportService.insertDatasource(datasource);
        return result > 0 ? success("新增成功") : error("新增失败");
    }

    /**
     * 修改数据源配置
     */
    @RequiresPermissions("report:config:edit")
    @Log(title = "数据源配置", businessType = BusinessType.UPDATE)
    @PutMapping("/datasource")
    @ApiOperation("修改数据源配置")
    public AjaxResult updateDatasource(@RequestBody ReportDatasource datasource) {
        datasource.setUpdateBy(SecurityUtils.getUsername());
        int result = customReportService.updateDatasource(datasource);
        return result > 0 ? success("修改成功") : error("修改失败");
    }

    /**
     * 新增字段配置
     */
    @RequiresPermissions("report:config:add")
    @Log(title = "字段配置", businessType = BusinessType.INSERT)
    @PostMapping("/field")
    @ApiOperation("新增字段配置")
    public AjaxResult addField(@RequestBody ReportField field) {
        int result = customReportService.insertField(field);
        return result > 0 ? success("新增成功") : error("新增失败");
    }

    /**
     * 批量新增字段配置
     */
    @RequiresPermissions("report:config:add")
    @Log(title = "字段配置", businessType = BusinessType.INSERT)
    @PostMapping("/field/batch")
    @ApiOperation("批量新增字段配置")
    public AjaxResult addFieldBatch(@RequestBody List<ReportField> fields) {
        int result = customReportService.insertFieldBatch(fields);
        return result > 0 ? success("新增成功") : error("新增失败");
    }

    /**
     * 修改字段配置
     */
    @RequiresPermissions("report:config:edit")
    @Log(title = "字段配置", businessType = BusinessType.UPDATE)
    @PutMapping("/field")
    @ApiOperation("修改字段配置")
    public AjaxResult updateField(@RequestBody ReportField field) {
        int result = customReportService.updateField(field);
        return result > 0 ? success("修改成功") : error("修改失败");
    }

    /**
     * 删除字段配置
     */
    @RequiresPermissions("report:config:remove")
    @Log(title = "字段配置", businessType = BusinessType.DELETE)
    @DeleteMapping("/field/{dsCode}/{fieldCode}")
    @ApiOperation("删除字段配置")
    public AjaxResult deleteField(
        @PathVariable String dsCode,
        @PathVariable String fieldCode) {
        int result = customReportService.deleteField(dsCode, fieldCode);
        return result > 0 ? success("删除成功") : error("删除失败");
    }

    /**
     * 新增关联配置
     */
    @RequiresPermissions("report:config:add")
    @Log(title = "关联配置", businessType = BusinessType.INSERT)
    @PostMapping("/relation")
    @ApiOperation("新增关联配置")
    public AjaxResult addRelation(@RequestBody ReportRelation relation) {
        int result = customReportService.insertRelation(relation);
        return result > 0 ? success("新增成功") : error("新增失败");
    }

    /**
     * 修改关联配置
     */
    @RequiresPermissions("report:config:edit")
    @Log(title = "关联配置", businessType = BusinessType.UPDATE)
    @PutMapping("/relation")
    @ApiOperation("修改关联配置")
    public AjaxResult updateRelation(@RequestBody ReportRelation relation) {
        int result = customReportService.updateRelation(relation);
        return result > 0 ? success("修改成功") : error("修改失败");
    }
}