package org.springblade.flow.visual.onlinedev.controller;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.flowable.engine.RuntimeService;
import org.springblade.bi.client.model.CubeDataModel;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.flow.base.ActionResult;
import org.springblade.flow.base.util.FlowDataUtil;
import org.springblade.flow.config.ConfigValueUtil;
import org.springblade.flow.database.exception.DataException;
import org.springblade.flow.datalog.service.FormDataLogService;
import org.springblade.flow.engine.entity.FlowEngineEntity;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springblade.flow.engine.service.FlowTaskService;
import org.springblade.flow.exception.WorkFlowException;
import org.springblade.flow.model.visiual.OnlineDevData;
import org.springblade.flow.model.visiual.fields.FieldsModel;
import org.springblade.flow.util.CacheKeyUtil;
import org.springblade.flow.util.JsonUtil;
import org.springblade.flow.util.JsonUtilEx;
import org.springblade.flow.util.RedisUtil;
import org.springblade.flow.util.StringUtil;
import org.springblade.flow.util.UserProvider;
import org.springblade.flow.util.file.FileExport;
import org.springblade.flow.visual.base.dto.PermJsonDto;
import org.springblade.flow.visual.base.entity.DataPermissionUser;
import org.springblade.flow.visual.base.entity.VisualdevDataPermission;
import org.springblade.flow.visual.base.entity.VisualdevEntity;
import org.springblade.flow.visual.base.service.VisualdevService;
import org.springblade.flow.visual.base.service.impl.DataPermissionUserService;
import org.springblade.flow.visual.base.service.impl.VisualdevDataPermissionService;
import org.springblade.flow.visual.base.util.VisualUtils;
import org.springblade.flow.visual.onlinedev.common.dynamic.DataSourceService;
import org.springblade.flow.visual.onlinedev.common.excel.ExcelFormParam;
import org.springblade.flow.visual.onlinedev.common.formdata.FormDataWithTableService;
import org.springblade.flow.visual.onlinedev.common.relation.RelationUtil;
import org.springblade.flow.visual.onlinedev.entity.VisualdevModelDataEntity;
import org.springblade.flow.visual.onlinedev.model.BatchRemoveIdsVo;
import org.springblade.flow.visual.onlinedev.model.ColumnDataInfoVO;
import org.springblade.flow.visual.onlinedev.model.DataInfoVO;
import org.springblade.flow.visual.onlinedev.model.FlowTemplateInfoVo;
import org.springblade.flow.visual.onlinedev.model.FormDataInfoVO;
import org.springblade.flow.visual.onlinedev.model.PaginationModel;
import org.springblade.flow.visual.onlinedev.model.VisualdevModelDataCrForm;
import org.springblade.flow.visual.onlinedev.model.VisualdevModelDataInfoVO;
import org.springblade.flow.visual.onlinedev.model.VisualdevModelDataUpForm;
import org.springblade.flow.visual.onlinedev.service.VisualdevModelDataService;
import org.springblade.flow.visual.onlinedev.util.AutoFeildsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.RestController;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.core.util.StrUtil;

import cn.hutool.core.collection.CollUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 0代码无表开发
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Slf4j
@Api(tags = "0表单在线设计相关接口", value = "OnlineDev")
@RestController
@RequestMapping("/paas/visualdev/OnlineDev")
public class VisualdevModelDataController extends BladeController {

	@Autowired
	private VisualdevModelDataService visualdevModelDataService;
	@Autowired
	private VisualdevService visualdevService;
	@Autowired
	private ConfigValueUtil configValueUtil;
	@Autowired
	private UserProvider userProvider;
	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private FileExport fileExport;
	@Autowired
	private FlowEngineService flowEngineService;

	@Autowired
	private DataSourceService dblinkService;
	@Resource
	private RuntimeService runtimeService;

	@Autowired
	private FormDataWithTableService formDataWithTableService;

	@Autowired
	private FlowTaskService flowTaskService;

	@Autowired
	private FlowDataUtil flowDataUtil;

	@Autowired
	private VisualdevDataPermissionService dataPermissionService;

	@Autowired
	private DataPermissionUserService dataPermissionUserService;

	@Autowired
	private FormDataLogService logService;

	@Value("${blade.file.uploadPath}")
	private String uploadDir;

	@ApiOperation("表单操作 - 获取列表表单配置JSON")
	@GetMapping("/{modelId}/Config")
	public ActionResult<Object> getData(@PathVariable("modelId") String modelId) {
		VisualdevEntity entity = visualdevService.getInfo(modelId);
		if (entity == null) {
			return ActionResult.fail("功能不存在");
		}
		DataInfoVO vo = JsonUtil.getJsonToBean(entity, DataInfoVO.class);
		if (StringUtil.isNotEmpty(entity.getWebType())) {
			if (entity.getWebType() != null && entity.getWebType().equals("3")) {
				try {
					FlowEngineEntity engineEntity = flowEngineService.getInfo(entity.getFlowId());
					vo.setFlowEnCode(engineEntity.getEnCode());
					vo.setFlowId(entity.getFlowId());
				} catch (WorkFlowException e) {
					e.printStackTrace();
				}
			}
		}

		vo.setDbLinkId(entity.getDbLinkId());
		vo.setIdKey(formDataWithTableService.getMainTablePrimaryKeyId(modelId));
		return ActionResult.success(vo);
	}

	@ApiOperation("表单操作 - 获取列表配置JSON")
	@GetMapping("/{modelId}/ColumnData")
	public ActionResult<FormDataInfoVO> getColumnData(@PathVariable("modelId") String modelId) {
		VisualdevEntity entity = visualdevService.getInfo(modelId);
		FormDataInfoVO vo = JsonUtil.getJsonToBean(entity, FormDataInfoVO.class);
		return ActionResult.success(vo);
	}

	@ApiOperation("表单操作 - 获取表单配置JSON")
	@GetMapping("/{modelId}/FormData")
	public ActionResult<ColumnDataInfoVO> getFormData(@PathVariable("modelId") String modelId) {
		VisualdevEntity entity = visualdevService.getInfo(modelId);
		ColumnDataInfoVO vo = JsonUtil.getJsonToBean(entity, ColumnDataInfoVO.class);
		return ActionResult.success(vo);
	}

	@ApiOperation("表单操作 - 获取工作流模板JSON")
	@GetMapping("/{modelId}/FlowTemplate")
	public ActionResult<FlowTemplateInfoVo> getFlowTemplate(@PathVariable("modelId") String modelId) {
		VisualdevEntity entity = visualdevService.getInfo(modelId);
		FlowTemplateInfoVo vo = JsonUtil.getJsonToBean(entity, FlowTemplateInfoVo.class);
		return ActionResult.success(vo);
	}

	@ApiOperation("数据操作 - 分页查询")
	@PostMapping("/{modelId}/List")
	public ActionResult<?> list(@PathVariable("modelId") String modelId, @RequestBody PaginationModel paginationModel)
			throws ParseException, IOException, SQLException, DataException {
		VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
		return formDataWithTableService.list(visualdevEntity, paginationModel);
	}

	@ApiOperation("数据操作 - 数据详情")
	@GetMapping("/{modelId}/{id}")
	public ActionResult<VisualdevModelDataInfoVO> info(@PathVariable("id") String id,
			@PathVariable("modelId") String modelId) throws DataException, ParseException, SQLException, IOException {
		VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
		// 有表
		if (!StringUtil.isEmpty(visualdevEntity.getTables())
				&& !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getTables())) {
			VisualdevModelDataInfoVO vo = visualdevModelDataService.tableInfo(id, visualdevEntity);
			return ActionResult.success(vo);
		}
		// 无表
		VisualdevModelDataEntity entity = visualdevModelDataService.getInfo(id);
		Map<String, Object> formData = JsonUtil.stringToMap(visualdevEntity.getFormData());
		List<FieldsModel> modelList = JsonUtil.getJsonToList(formData.get("fields").toString(), FieldsModel.class);
		// 去除模板多级控件
		modelList = VisualUtils.deleteMore(modelList);
		String data = AutoFeildsUtil.autoFeilds(modelList, entity.getData());
		entity.setData(data);
		VisualdevModelDataInfoVO vo = JsonUtilEx.getJsonToBeanEx(entity, VisualdevModelDataInfoVO.class);
		return ActionResult.success(vo);
	}

	@ApiOperation("数据操作 - 详情(带转换数据)")
	@GetMapping("/{modelId}/{id}/DataChange")
	public ActionResult<VisualdevModelDataInfoVO> infoWithDataChange(@PathVariable("modelId") String modelId,
			@PathVariable("id") String id) throws DataException, ParseException, IOException, SQLException {
		VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
		if (redisUtil.exists(CacheKeyUtil.VISIUALDATA + modelId)) {
			redisUtil.remove(CacheKeyUtil.VISIUALDATA + modelId);
		}
		// 有表
		if (!StringUtil.isEmpty(visualdevEntity.getTables())
				&& !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getTables())) {
			VisualdevModelDataInfoVO vo = visualdevModelDataService.tableInfoDataChange(id, visualdevEntity);
			return ActionResult.success(vo);
		}
		// 无表
		VisualdevModelDataInfoVO vo = visualdevModelDataService.infoDataChange(id, visualdevEntity);
		return ActionResult.success(vo);
	}

	@ApiOperation("数据操作 - 添加")
	@PostMapping("/{modelId}")
	public ActionResult<String> create(@PathVariable("modelId") String modelId,
			@RequestBody VisualdevModelDataCrForm visualdevModelDataCrForm) throws WorkFlowException {
		ActionResult<String> ret = formDataWithTableService.add(modelId, visualdevModelDataCrForm);
		if (ret.getCode() == 200) {
			Map<String, Object> oldData = JsonUtil.stringToMap(visualdevModelDataCrForm.getOldData());
			Map<String, Object> newData = JsonUtil.stringToMap(visualdevModelDataCrForm.getData());
			logService.saveLog(modelId, oldData, newData);
		}
		return ret;
	}

	@ApiOperation("数据操作 - Excel导入")
	@PostMapping("/createBatch")
	public ActionResult<String> createBatch(@RequestBody ExcelFormParam params) throws WorkFlowException, SQLException {
		if (params == null) {
			return ActionResult.fail("缺少参数");
		}

		if (CollUtil.isEmpty(params.getList())) {
			return ActionResult.fail("缺少字段和索引映射");
		}

		String filePath = uploadDir + params.getFile().replace("uploads/", "");
		File excelFile = new File(filePath);
		if (excelFile == null || !excelFile.exists()) {
			return ActionResult.fail("Excel文件不存在");
		}

		String modelId = params.getModelId();
		VisualdevEntity formInfo = visualdevService.getInfo(modelId);
		if (formInfo == null) {
			return ActionResult.fail("表单不存在");
		}

		CubeDataModel cubeData = dblinkService.getCubeData(formInfo.getDbLinkId());
		if (RelationUtil.hasLinkTable(cubeData)) {
			return formDataWithTableService.batchAddForMultipleTable(cubeData, params.getWithHeader(), formInfo,
					params.getList(), excelFile);
		}

		return formDataWithTableService.batchAddForSingleTable(cubeData, params.getWithHeader(), formInfo,
				params.getList(), excelFile);
	}

	@ApiOperation("数据操作 - 更新")
	@PutMapping("/{modelId}/{id}")
	public ActionResult<?> update(@PathVariable("id") String id, @PathVariable("modelId") String modelId,
			@RequestBody VisualdevModelDataUpForm visualdevModelDataUpForm)
			throws DataException, SQLException, WorkFlowException {
		if (StrUtil.isBlank(id)) {
			return ActionResult.fail("缺少ID，无法修改");
		}

		VisualdevEntity formInfo = visualdevService.getInfo(modelId);
		if (formInfo == null) {
			return ActionResult.fail("表单不存在");
		}

		ActionResult<?> ret = formDataWithTableService.update(formInfo, id, visualdevModelDataUpForm);

		if (ret.getCode() == 200) {
			Map<String, Object> oldData = JsonUtil.stringToMap(visualdevModelDataUpForm.getOldData());
			Map<String, Object> newData = JsonUtil.stringToMap(visualdevModelDataUpForm.getData());
			logService.saveLog(modelId, oldData, newData);
		}
		return ret;
	}

	@ApiOperation("数据操作 - 删除（暂仅支持单表）")
	@DeleteMapping("/{modelId}/{id}")
	public ActionResult<String> delete(@PathVariable("id") String id, @PathVariable("modelId") String modelId)
			throws DataException, SQLException, WorkFlowException {
		if (StrUtil.isBlank(id)) {
			return ActionResult.fail("缺少ID，无法删除");
		}

		VisualdevEntity formInfo = visualdevService.getInfo(modelId);
		if (formInfo == null) {
			return ActionResult.fail("表单不存在");
		}

		List<String> idList = new ArrayList<>();
		idList.add(id);
		return formDataWithTableService.delete(formInfo, idList);
	}

	@ApiOperation("数据操作 - 批量删除")
	@PostMapping("/batchDelete/{modelId}")
	public ActionResult<String> beachDelete(@RequestBody BatchRemoveIdsVo idsVo,
			@PathVariable("modelId") String modelId) throws DataException, SQLException, WorkFlowException {
		List<String> idList = Arrays.asList(idsVo.getIds());
		if (CollUtil.isEmpty(idList)) {
			return ActionResult.fail("缺少ID，无法删除");
		}

		VisualdevEntity formInfo = visualdevService.getInfo(modelId);
		if (formInfo == null) {
			return ActionResult.fail("表单不存在");
		}

		return formDataWithTableService.delete(formInfo, idList);
	}

	@ApiOperation("数据操作 - 查询操作权限")
	@PostMapping("/getPerm/{modelId}")
	public R getPerm(@PathVariable("modelId") String modelId) {
		Long userId = getUser().getUserId();
		List<String> result = new ArrayList<>();
		// 查询用户所属权限
		List<DataPermissionUser> dataPermissionUsers = dataPermissionUserService
				.list(Wrappers.<DataPermissionUser>lambdaQuery().eq(DataPermissionUser::getUserId, userId));
		if (dataPermissionUsers != null && dataPermissionUsers.size() > 0) {
			for (DataPermissionUser dataPermissionUser : dataPermissionUsers) {
				VisualdevDataPermission visualdevDataPermission = dataPermissionService.getOne(Wrappers
						.<VisualdevDataPermission>lambdaQuery().eq(VisualdevDataPermission::getVisualdevId, modelId)
						.eq(VisualdevDataPermission::getDataPermId, dataPermissionUser.getDataPermId()));
				if (visualdevDataPermission != null) {
					String permJson = visualdevDataPermission.getPermJson();
					List<PermJsonDto> permJsonDtos = JSON.parseArray(permJson, PermJsonDto.class);
					for (PermJsonDto permJsonDto : permJsonDtos) {
						Integer value = permJsonDto.getPermValue();
						if (!result.contains(permJsonDto.getPermKey()) && value == 1) {
							result.add(permJsonDto.getPermKey());
						}
					}
				}
			}
		}
		if (result.size() == 0) {
			// 取默认权限
			VisualdevDataPermission visualdevDataPermission = dataPermissionService.getOne(
					Wrappers.<VisualdevDataPermission>lambdaQuery().eq(VisualdevDataPermission::getVisualdevId, modelId)
							.eq(VisualdevDataPermission::getIsDefault, 1));
			if (visualdevDataPermission != null) {
				String permJson = visualdevDataPermission.getPermJson();
				List<PermJsonDto> permJsonDtos = JSON.parseArray(permJson, PermJsonDto.class);
				for (PermJsonDto permJsonDto : permJsonDtos) {
					Integer value = permJsonDto.getPermValue();
					if (!result.contains(permJsonDto.getPermKey()) && value == 1) {
						result.add(permJsonDto.getPermKey());
					}
				}
			}

		}
		return R.data(result);
	}

//	@ApiOperation("数据操作 - 导出")
//	@PostMapping("/{modelId}/Actions/Export")
//	public ActionResult<DownloadVO> export(@PathVariable("modelId") String modelId,
//			@RequestBody PaginationModelExport paginationModelExport)
//			throws ParseException, IOException, SQLException, DataException {
//		VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
//		String[] keys = paginationModelExport.getSelectKey();
//		// 关键字过滤
//		List<Map<String, Object>> realList = visualdevModelDataService.exportData(keys, paginationModelExport,
//				visualdevEntity);
//		UserInfo userInfo = userProvider.get();
//		DownloadVO vo = VisualUtils.createModelExcel(visualdevEntity.getFormData(),
//				configValueUtil.getTemporaryFilePath(), realList, keys, userInfo);
//		return ActionResult.success(vo);
//	}

}
