package com.ozs.mdm.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import com.ozs.mdm.service.AccountApi;
import com.ozs.mdm.service.StorageManageService;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.ozs.mdm.dto.CreateTableCopyDTO;
import com.ozs.mdm.dto.MdmCreateTableDTO;
import com.ozs.mdm.dto.MdmDimColumnType;
import com.ozs.mdm.dto.MdmDimCreateOption;
import com.ozs.mdm.dto.MdmInfoColumn;
import com.ozs.mdm.dto.MdmInfoDatabase;
import com.ozs.mdm.dto.MdmInfoTable;
import com.ozs.mdm.dto.UpdateTableDTO;
import com.ozs.mdm.util.R;
import com.ozs.mdm.util.S;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

@Api(tags = { "数据管理—>元数据管理" })
@RestController
public class StorageManageController {
	private final Logger log = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private AccountApi accountApi;
	@Autowired
	private StorageManageService storageManageServicel;

	@ApiOperation("获取已建数据库列表选项-仅目标库")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "resourceName", value = "资源名称(模糊搜索)", required = false, paramType = "query", dataType = "String") })
	@GetMapping("/mdm/storageManage/listDatabaseOption")
	public R<List<MdmInfoDatabase>> listDatabaseOption(
			@RequestParam(name = "resourceName", required = false) String resourceName) {
		try {
			return storageManageServicel.listDatabaseOption(resourceName);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("获取已建数据库列表选项-全部，包括原始库")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "resourceName", value = "资源名称(模糊搜索)", required = false, paramType = "query", dataType = "String") })
	@GetMapping("/mdm/storageManage/listDatabaseOptionAll")
	public R<List<MdmInfoDatabase>> listDatabaseOptionAll(
			@RequestParam(name = "resourceName", required = false) String resourceName) {
		try {
			return storageManageServicel.listDatabaseOptionAll(resourceName);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("获取建表方式选项")
	@GetMapping("/mdm/storageManage/listCreateTableOption")
	public R<List<MdmDimCreateOption>> listCreateTableOption() {
		try {
			return storageManageServicel.listCreateTableOption();
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("建表-向导方式创建表")
	@PostMapping("/mdm/storageManage/createTable")
	public R<String> createTable(@RequestBody MdmCreateTableDTO tableDto, @RequestHeader("token") String token) {
		try {
			tableDto.setUpdateUserId(accountApi.parseTokenId(token));
			return storageManageServicel.createTable(tableDto);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR, "建表失败");
		}
	}

	@ApiOperation("下载模板")
	@GetMapping("/mdm/storageManage/downloadTemplateColums")
	public void downloadTemplateColums(HttpServletResponse response) throws Exception {
		InputStream inputStream = null;
		ServletOutputStream servletOutputStream = null;
		File f = null;
		try {

			String fileName = "template-colums.xlsx";
			String filePath = storageManageServicel.getTemplateColums(fileName.substring(0, fileName.lastIndexOf(".")));
			response.setContentType("application/vnd.ms-excel");
			response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
			response.addHeader("charset", "utf-8");
			response.addHeader("Pragma", "no-cache");
			String encodeName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
			response.setHeader("Content-Disposition",
					"attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);
			f = new File(filePath);
			inputStream = new FileInputStream(f);
			servletOutputStream = response.getOutputStream();
			IOUtils.copy(inputStream, servletOutputStream);
			response.flushBuffer();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (servletOutputStream != null) {
					servletOutputStream.close();
					servletOutputStream = null;
				}
				if (inputStream != null) {
					inputStream.close();
					f.delete();
					inputStream = null;
				}
				// 召唤jvm的垃圾回收器
				System.gc();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@ApiOperation(value = "字段模板上传")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "file", value = "报表文件", required = true, paramType = "form", dataType = "__file") })
	@PostMapping(value = "/mdm/storageManage/loadTemplateColums", consumes = "multipart/*", headers = "content-type=multipart/form-data")
	public R<List<Map<String, Object>>> loadReportOutbound(@RequestParam("file") MultipartFile file) {
		try {
			return storageManageServicel.loadTemplateColums(file);
		} catch (Exception e) {
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("建表-DDL方式创建表")
	@PostMapping("/mdm/storageManage/createTableByDDL")
	public R<String> createTableByDDL(@RequestBody MdmCreateTableDTO tableDto, @RequestHeader("token") String token) {
		try {
			tableDto.setUpdateUserId(accountApi.parseTokenId(token));
			return storageManageServicel.createTableByDDL(tableDto);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR, "建表失败");
		}
	}

	@ApiOperation("获取数据表信息")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tableName", value = "表名称", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "tableComment", value = "表中文名称", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "databaseId", value = "所属数据库ID", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "page", value = "当前页数", required = false, paramType = "query", dataType = "Integer"),
			@ApiImplicitParam(name = "sort", value = "排序字段", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "order", value = "排序方式", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, paramType = "query", dataType = "Integer") })
	@GetMapping("/mdm/storageManage/listTable")
	public R<List<MdmInfoTable>> listTable(@RequestParam(name = "tableName", required = false) String tableName,
			@RequestParam(name = "tableComment", required = false) String tableComment,
			@RequestParam(name = "databaseId", required = false) String databaseId,
			@RequestParam(required = false, defaultValue = "update_time") String sort,
			@RequestParam(required = false) String order,
			@RequestParam(required = false, defaultValue = "1") Integer page,
			@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
		try {
			return storageManageServicel.listTable(tableName, tableComment, databaseId, sort, order, page, pageSize);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("获取数据表信息-扫描数据源，包括原始库和目标库")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tableName", value = "表名称", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "tableComment", value = "表中文名称", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "databaseId", value = "所属数据库ID", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "page", value = "当前页数", required = false, paramType = "query", dataType = "Integer"),
			@ApiImplicitParam(name = "sort", value = "排序字段", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "order", value = "排序方式", required = false, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, paramType = "query", dataType = "Integer") })
	@GetMapping("/mdm/storageManage/listTableScan")
	public R<List<MdmInfoTable>> listTableScan(@RequestParam(name = "tableName", required = false) String tableName,
			@RequestParam(name = "tableComment", required = false) String tableComment,
			@RequestParam(name = "databaseId", required = false) String databaseId,
			@RequestParam(required = false, defaultValue = "update_time") String sort,
			@RequestParam(required = false) String order,
			@RequestParam(required = false, defaultValue = "1") Integer page,
			@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
		try {
			return storageManageServicel.listTableScan(tableName, tableComment, databaseId, sort, order, page,
					pageSize);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("删表接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tableId", value = "数据表ID", required = false, paramType = "path", dataType = "String") })
	@DeleteMapping("/mdm/storageManage/removeTableById/{tableId}")
	public R<String> removeTableById(@PathVariable(name = "tableId", required = false) String tableId) {
		try {
			return storageManageServicel.removeTableById(tableId);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR, "删表失败");
		}
	}

	@ApiOperation("修改表接口")
	@PutMapping("/mdm/storageManage/updateTable")
	public R<String> updateTable(@RequestBody UpdateTableDTO uTableDto, @RequestHeader("token") String token) {
		try {
			uTableDto.setUpdateUserId(accountApi.parseTokenId(token));
			return storageManageServicel.updateTable(uTableDto);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR, "修改失败");
		}
	}

	@ApiOperation("根据表ID获取表信息接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tableId", value = "数据表ID", required = false, paramType = "path", dataType = "String") })
	@GetMapping("/mdm/storageManage/getTableInfoById/{tableId}")
	public R<MdmCreateTableDTO> getTableInfoById(@PathVariable(name = "tableId", required = false) String tableId) {
		try {
			return storageManageServicel.getTableInfoById(tableId);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("根据表ID获取表信息接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "tableId", value = "数据表ID", required = false, paramType = "path", dataType = "String") })
	@GetMapping("/mdm/storageManage/listColumsByTableId/{tableId}")
	public R<List<MdmInfoColumn>> listColumsByTableId(
			@PathVariable(name = "tableId", required = false) String tableId) {
		try {
			return storageManageServicel.listColumsByTableId(tableId);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("根据数据库类型获取字段类型")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "resourceType", value = "数据库资源类型1(hive) 2(mysql)", required = false, paramType = "path", dataType = "Integer") })
	@GetMapping("/mdm/storageManage/listColumTypeByDatabaseType/{resourceType}")
	public R<List<MdmDimColumnType>> listColumTypeByDatabaseType(
			@PathVariable(name = "resourceType", required = false) Integer resourceType) {
		try {
			return storageManageServicel.listColumTypeByDatabaseType(resourceType);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}

	@ApiOperation("建表-扫描批量复制表")
	@PostMapping("/mdm/storageManage/createTableByCopy")
	public R<String> createTableByCopy(@RequestBody CreateTableCopyDTO tableCopyDto,
			@RequestHeader("token") String token) {
		tableCopyDto.setUpdateUserId(accountApi.parseTokenId(token));
		try {
			return storageManageServicel.createTableByCopy(tableCopyDto);
		} catch (Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
	}
}
