package com.artfess.dataShare.dataCollect.controller;


import com.artfess.base.annotation.ApiGroup;
import com.artfess.base.constants.ApiGroupConsts;
import com.artfess.base.controller.BaseController;
import com.artfess.base.enums.ResponseErrorEnums;
import com.artfess.base.exception.ApplicationException;
import com.artfess.base.model.CommonResult;
import com.artfess.base.query.FieldRelation;
import com.artfess.base.query.PageList;
import com.artfess.base.query.QueryFilter;
import com.artfess.base.query.QueryOP;
import com.artfess.base.util.*;
import com.artfess.base.valid.AddGroup;
import com.artfess.dataShare.dataCollect.manager.BizClusterInfoManager;
import com.artfess.dataShare.dataCollect.manager.BizClusterInfoModeManager;
import com.artfess.dataShare.dataCollect.manager.BizClusterTableManager;
import com.artfess.dataShare.dataCollect.manager.BizClusterTableTriggerManager;
import com.artfess.dataShare.dataCollect.model.BizClusterInfo;
import com.artfess.dataShare.dataCollect.model.BizClusterInfoMode;
import com.artfess.dataShare.dataCollect.model.BizClusterTable;
import com.artfess.dataShare.dataCollect.model.BizClusterTableTrigger;
import com.artfess.dataShare.dataCollect.vo.TableDetailVo;
import com.artfess.dataShare.dataResource.ods.vo.CopyTableVo;
import com.artfess.dataShare.factory.QueryParamVo;
import com.artfess.dataShare.factory.QueryResultData;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;

/**
 * 数据汇聚表信息 前端控制器
 *
 * @company 阿特菲斯信息技术有限公司
 * @author WH
 * @since 2024-11-07
 */
@RestController
@RequestMapping("/biz/dataCollect/clusterTable/v1/")
@ApiGroup(group = {ApiGroupConsts.GROUP_BIZ_DATASHARE})
@Api(tags = "数据汇聚-数据汇聚表信息")
public class BizClusterTableController extends BaseController<BizClusterTableManager, BizClusterTable> {

    @Resource
    BizClusterTableManager tableManager;

    @Resource
    BizClusterInfoManager infoManager;


    @Resource
    BizClusterTableTriggerManager tableTriggerManager;

    @Resource
    BizClusterInfoModeManager infoModeManager;

    //@Resource
    //BizClusterMouldManager mouldManager;

    @PostMapping("/")
    @ApiOperation("添加实体的接口")
    public CommonResult<String> create(@ApiParam(name = "model", value = "实体信息") @Validated({AddGroup.class}) @RequestBody BizClusterTable t) {
        if(StringUtil.isEmpty(t.getId())){
            BizClusterInfo info=this.infoManager.get(t.getClusterId());
            t.setDeployed(0);
            t.setIsCreateTable(0);
            t.setIsDele("0");
            t.setTableNameEn(info.getSysTableCode()+"_"+t.getTableNameEn());
        }
        boolean result = baseService.save(t);
        if (!result) {
            return new CommonResult<>(ResponseErrorEnums.FAIL_OPTION, null);
        }
        return new CommonResult<>();
    }

    @PostMapping("/importFile")
    @ApiOperation(value = "导入数据汇聚表信息", httpMethod = "POST", notes = "导入数据汇聚表信息")
    public CommonResult<String> export(@RequestParam(value = "file", required = true) MultipartFile file,@RequestParam String clusterInfoId) throws Exception {
        this.tableManager.export(file,clusterInfoId);
        return new CommonResult<String>(true, "导入数据汇聚表成功");
    }

    /*//下载模板  HttpUtil.downLoadFile(response, path, file.getName()); 改为前端自己做
    @PostMapping(value = "/downloadExcelTemplate")
    @ApiOperation("下载数据项模板")
    public void downloadFileLic(HttpServletResponse response) throws Exception {
        String path = "";
        File file = new File(path);
        HttpUtil.downLoadFile(response, path, file.getName());
    }*/

    //发布表
    @PostMapping(value = "/Deploy/{tableId}")
    @ApiOperation("直接发布表，创建实体表-使用默认的SQL")
    public CommonResult<String> Deploy(@PathVariable String tableId) throws Exception {
        this.tableManager.Deploy(tableId);
        return new CommonResult<String>(true, "发布表成功");
    }

    @PostMapping(value = "/saveTableVo")
    @ApiOperation("保存查询表信息、字段信息、模型")
    public CommonResult<String> saveTableVo(@RequestBody TableDetailVo vo) throws Exception {
        this.tableManager.saveTableVo(vo);
        return new CommonResult<String>(true, "维护成功");
    }

    @PostMapping(value = "/queryTableVo/{tableId}")
    @ApiOperation("根据表查询表信息、字段信息、模型")
    public TableDetailVo queryTableVo(@PathVariable String tableId) throws Exception {
        TableDetailVo vo=this.tableManager.queryTableVo(tableId);
        return vo;
    }

    //todo 数据查询  分页，加搜索、排序
    /*@PostMapping(value = "/queryTableData")
    @ApiOperation("数据查询  分页，加搜索、排序")
    public Map<String,Object> queryTableData(String tableId,Map<String,String> queryParam,String orderField,Integer page,Integer pageSize) throws Exception {
        return this.tableManager.queryTableData(tableId,queryParam,orderField,page,pageSize);
    }*/

    @PostMapping(value = "/queryTableData")
    @ApiOperation("数据查询  分页，加搜索、排序")
    public QueryResultData queryTableData(@RequestBody QueryParamVo queryParamVo) throws Exception {
        return this.tableManager.queryTableData(queryParamVo);
    }

    //todo 查询表和触发器创建结果 返回创建SQL/触发器
    @PostMapping(value = "/queryTableInfo/{tableId}")
    @ApiOperation("根据表查询建表语句、触发器语句、创建结果")
    public Map<String,Object> queryTableInfo(@PathVariable String tableId) throws Exception {
        Map<String,Object> result=new HashMap<>();
        BizClusterTable table=this.getById(tableId);
        if(null==table){
            throw new ApplicationException("未查询到表");
        }
        //BizClusterMould mould=this.mouldManager.getById(table.getMouldId());
        BizClusterInfoMode infoMode = infoModeManager.getById(table.getClusterId());
//        String dbAlias=table.getDbSourceId();
        String tableName=table.getTableNameEn();
        JdbcTemplate template = DataSourceUtil.getJdbcTempByDsAlias(infoMode.getDatabaseAlias());
        //查询触发器
        String queryTrigger="SELECT trigger_schema,trigger_name,event_manipulation,event_object_schema,event_object_table,action_statement\n" +
                "FROM information_schema.triggers\n" +
                "WHERE EVENT_OBJECT_TABLE = ?";
        List<Map<String,Object>> triggers=template.queryForList(queryTrigger,new Object[]{tableName});
        if(triggers.size()>0){
            result.put("is_created_trigger","1");
            List<Map<String,Object>> triggerSql=new ArrayList<>();
            for(Map<String,Object> map : triggers){
                String insertTigerSql="CREATE TRIGGER "+map.get("trigger_name")+"" + map.get("event_object_table") + "\n"+
                        "    AFTER "+map.get("event_manipulation")+"  ON " + tableName + " FOR EACH ROW \n" +map.get("action_statement");
                Map<String,Object> triggerMap=new HashMap<>();
                triggerMap.put("sql",insertTigerSql);
                triggerMap.put("name",map.get("trigger_name"));
                triggerMap.put("type",map.get("event_manipulation"));
                triggerSql.add(triggerMap);
            }
            result.put("trigger",triggers);
        }else{
            result.put("is_created_trigger","0");
            result.put("trigger",this.tableManager.queryTriggerSql(tableId));
        }


        //查询建表语句
       /* String queryCreateTable="SHOW CREATE TABLE "+tableName;
        Map<String,Object> tableSql=template.queryBizClusterTableap(queryCreateTable);
        if(tableSql.keySet().size()>0){
            result.put("is_created_table","1");
            result.put("createTableSql",tableSql.get("Create Table"));
        }else{*/
            result.put("is_created_table",table.getIsCreateTable());
            result.put("createTableSql",tableManager.queryTableSql(tableId));
        //}
        return result;
    }

    //手动建表和触发器
    @PostMapping(value = "/createdTable/{tableId}")
    @ApiOperation("手动建表")
    public CommonResult<String> createdTable(@PathVariable String tableId) throws Exception {
        this.tableManager.createdTable(tableId);
        return new CommonResult<String>(true, "手动建表成功");
    }

    @PostMapping(value = "/createdTrigger/{tableId}")
    @ApiOperation("手动建触发器")
    public CommonResult<String> createdTrigger(@PathVariable String tableId) throws Exception {
        this.tableManager.createdTrigger(tableId);
        return new CommonResult<String>(true, "手动建触发器成功");
    }

    //导出数据
    @RequestMapping(value = "downloadMainTempFile/{tableId}", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "下载导入的模板", httpMethod = "POST", notes = "下载导入的模板")
    public void downloadMainTempFile(HttpServletResponse response,
                                     @ApiParam(name = "tableId", value = "模板别名", required = true) @PathVariable String tableId) throws Exception {
        baseService.downloadMainTempFile(response, tableId);
    }

    @PostMapping(value = "importMain", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "导入汇聚主表数据", httpMethod = "POST", notes = "导入汇聚主表数据")
    public CommonResult<String> importMain(@RequestParam(value = "file", required = true) MultipartFile file,
                                           @RequestParam(value = "tableId", required = true) String tableId) throws Exception {
        baseService.importMain(file, tableId);
        return new CommonResult<>("导入主表数据成功");
    }

    //下载建表语句和触发器SQL文件
    @PostMapping(value = "downTableSql/{tableId}", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "下载建表语句和触发器SQL文件", httpMethod = "POST", notes = "下载建表语句和触发器SQL文件")
    public void downTableSql(HttpServletResponse response,@ApiParam(name = "tableId", value = "数据表ID") @PathVariable String tableId) throws Exception {
        BizClusterTable table=tableManager.getById(tableId);
        QueryWrapper queryWrapper =new QueryWrapper();
        queryWrapper.eq("table_id_",tableId);
        List<BizClusterTableTrigger> list=tableTriggerManager.list(queryWrapper);
        String tableSql=table.getCreateTableSql();
        StringBuffer text=new StringBuffer("创建表SQL:\n");
        text.append(tableSql);
        for(BizClusterTableTrigger item : list){
            String triggerSql=item.getTriggerSql();
            text.append("\n").append(item.getName()).append("\n").append(triggerSql);
        }
        String rootRealPath = (FileUtil.getIoTmpdir() + "/temp/").replace("/", File.separator);
        FileUtil.createFolder(rootRealPath, true);
        String path = rootRealPath+File.separator+System.currentTimeMillis()+".txt";
        FileUtil.writeFile(path,text.toString());
        File file = new File(path);
        HttpUtil.downLoadFile(response, path, file.getName());
    }

    @RequestMapping(value = "list", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "查询汇聚主表数据", httpMethod = "POST", notes = "查询汇聚主表数据")
    public PageList<BizClusterTable> listJson(@ApiParam(name = "queryFilter", value = "通用查询对象") @RequestBody QueryFilter queryFilter) throws Exception {
        IPage<BizClusterTable> list = baseService.getClusterTableQueryList(queryFilter);
        PageList<BizClusterTable> pageList = new PageList<>(list);
        return pageList;
    }

    //-2024.01.05增加需求

    @PostMapping(value = "checkTableExists", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "验证表是否已经存在", httpMethod = "POST", notes = "验证表是否已经存在")
    public CommonResult<String> checkTableExists(@ApiParam(name = "clusterId", value = "汇聚方ID") @RequestParam String clusterId,
                                                 @ApiParam(name = "tableNameEn", value = "表英文名") @RequestParam String tableNameEn,
                                                 @ApiParam(name = "type", value = "发布类型(0:未有表发布，1:已有表发布)") @RequestParam(required = false) String type) throws Exception {
        boolean isExists=tableManager.checkTableExists(clusterId,tableNameEn);
        if ("1".equals(type)){
            if(isExists){
                return new CommonResult<>(true,"验证成功，可以发布");
            }
            return new CommonResult<>(false,"表"+tableNameEn+"不存在！");
        }
        if(isExists){
            return new CommonResult<>(false,"表"+tableNameEn+"已经存在，请更换表名");
        }
        return new CommonResult<>(true,"可以使用表名");
    }

    @PostMapping(value = "checkPhysicsTableExists", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "验证物理表是否已经存在", httpMethod = "POST", notes = "验证表是否已经存在")
    public CommonResult<String> checkPhysicsTableExists(@ApiParam(name = "clusterId", value = "汇聚方ID") @RequestParam String clusterId,
                                                 @ApiParam(name = "tableNameEn", value = "表英文名") @RequestParam String tableNameEn,
                                                 @ApiParam(name = "type", value = "发布类型(0:未有表发布，1:已有表发布)") @RequestParam(required = false) String type) throws Exception {
        boolean isExists=tableManager.checkPhysicsTableExists(clusterId,tableNameEn);
        if ("1".equals(type)){
            if(isExists){
                return new CommonResult<>(true,"验证成功，可以发布");
            }
            return new CommonResult<>(false,"表"+tableNameEn+"不存在！");
        }
        if(isExists){
            return new CommonResult<>(false,"表"+tableNameEn+"已经存在，请更换表名");
        }
        return new CommonResult<>(true,"可以使用表名");
    }

    @PostMapping(value = "copyTable", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "引用/复制创建的其他表", httpMethod = "POST", notes = "复制创建的其他表")
    public CommonResult<String> copyTable(@RequestBody CopyTableVo vo) throws Exception {
        tableManager.copyTable(vo);
        return new CommonResult<>(true,"操作成功");
    }

    @PostMapping(value = "queryTableSql/{tableId}", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "根据tableId查询建表语句", httpMethod = "POST", notes = "根据tableId查询建表语句")
    public CommonResult<String> queryTableSql(@ApiParam(name = "tableId", value = "数据表ID") @PathVariable String tableId) throws Exception {
        String tableSql=tableManager.queryTableSql(tableId);
        return CommonResult.success(tableSql,"获取成功");
    }

    @PostMapping(value = "saveTableSql", produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "保存建表SQL", httpMethod = "POST", notes = "保存建表SQL")
    public CommonResult<String> saveTableSql(@ApiParam(name = "tableId", value = "数据表ID") @RequestParam String tableId,
                                             @ApiParam(name = "tableSql", value = "建表语句") @RequestParam String tableSql) throws Exception {
        BizClusterTable table=tableManager.getById(tableId);
        table.setCreateTableSql(tableSql);
        tableManager.updateById(table);
        return new CommonResult<>(true,"保存成功");
    }

    @RequestMapping(value = "deployHaveTable", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "已有表发布-同时创建触发器", httpMethod = "POST", notes = "已有表发布")
    public CommonResult<String> deployHaveTable(@ApiParam(name = "tableId", value = "数据表ID") @RequestParam String tableId,
                                                @ApiParam(name = "createTrigger", value = "是否创建触发器 0否 1是") @RequestParam String createTrigger) throws Exception {
        tableManager.deployHaveTable(tableId,createTrigger);
        return new CommonResult<>(true,"已有表发布成功");
    }

    @RequestMapping(value = "deployDotHaveTable", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "未有表发布-同时创建触发器", httpMethod = "POST", notes = "未有表发布-同时创建触发器")
    public CommonResult<String> deployDotHaveTable(@ApiParam(name = "tableId", value = "数据表ID") @RequestParam String tableId,
                                                   @ApiParam(name = "tableSql", value = "建表语句") @RequestParam String tableSql,
                                                   @ApiParam(name = "createTrigger", value = "是否创建触发器 0否 1是") @RequestParam String createTrigger) throws Exception {
        tableManager.deployDotHaveTable(tableId,tableSql,createTrigger);
        return new CommonResult<>(true,"未有表发布成功");
    }

    @RequestMapping(value = "removeTable", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
    @ApiOperation(value = "刪除表-如果表已经创建同步删除实体表", httpMethod = "POST", notes = "刪除表-如果表已经创建同步删除实体表")
    public CommonResult<String> removeTable(@ApiParam(name = "tableId", value = "数据表ID") @RequestParam String tableId) throws Exception {
        tableManager.removeTable(tableId);
        return new CommonResult<>(true,"未有表发布成功");
    }
}
