package com.mortals.xhx.base.system.gentable.web;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.web.BaseCRUDJsonMappingController;
import com.mortals.xhx.base.system.gentable.model.*;
import com.mortals.xhx.base.system.gentable.service.GentableColumnService;
import com.mortals.xhx.base.system.gentable.service.GentableService;
import com.mortals.xhx.common.code.CacheServiceTypeEnum;
import com.mortals.xhx.common.code.DividedTableTypeEnum;
import com.mortals.xhx.common.code.GenTypeEnum;
import com.mortals.xhx.common.code.HtmlTypeEnum;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.mortals.framework.ap.SysConstains.MESSAGE_INFO;


/**
 * <p>Title: 代码生成业务表</p>
 * <p>Description: GentableController  </p>
 * <p>Copyright: Copyright &reg;  </p>
 * <p>Company: </p>
 *
 * @author zxfei
 * @version 1.0.0
 */
@RestController
@RequestMapping("gentable")
public class GentableController extends BaseCRUDJsonMappingController<GentableService, GentableForm, GentableEntity, Long> {

    @Autowired
    private GentableColumnService gentableColumnService;


    public GentableController() {
        super.setFormClass(GentableForm.class);
        super.setModuleDesc("代码生成业务表");
    }

    @Override
    protected void init(HttpServletRequest request, HttpServletResponse response, GentableForm form, Map<String, Object> model, Context context) {
        this.addDict(model, "dividedTableType", DividedTableTypeEnum.getEnumMap());
        this.addDict(model, "cacheServiceType", CacheServiceTypeEnum.getEnumMap());
        this.addDict(model, "genType", GenTypeEnum.getEnumMap());
        this.addDict(model, "htmlType", HtmlTypeEnum.getEnumMap());

        super.init(request, response, form, model, context);
    }

    @Override
    protected void doListBefore(HttpServletRequest request, HttpServletResponse response, GentableForm form, Map<String, Object> model, Context context) throws AppException {
        form.getQuery().setOrderField("tableName");
        super.doListBefore(request, response, form, model, context);
    }

    /**
     * 导入数据库列表
     *
     * @param form
     * @return
     */
    @PostMapping("/db/list")
    public String dblist(GentableForm form) {
        Map<String, Object> model = new HashMap<>();
        JSONObject ret = new JSONObject();
        String busiDesc = "查询数据库表";
        int code = VALUE_RESULT_SUCCESS;
        try {
            List<GentableEntity> list = this.service.selectDbTableList(form.getQuery());
            model.put("result", list);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
            this.doException(request, busiDesc, model, e);
        }
        ret.put(KEY_RESULT_CODE, code);
        ret.put(KEY_RESULT_QUERY, form.getQuery());
        ret.put(KEY_RESULT_DATA, model);
        return ret.toJSONString();
    }

    /**
     * 导入表到库中
     *
     * @param tables
     * @return
     */
    @PostMapping("/importTable")
    public String importTable(@RequestParam(value = "tables") String tables, @RequestParam(value = "appId") Long appId) {
        Map<String, Object> model = new HashMap<>();
        JSONObject ret = new JSONObject();
        String busiDesc = "查询数据库表";
        int code = VALUE_RESULT_SUCCESS;
        try {
            String[] tableNames = Convert.toStrArray(tables);
            //查询
            List<GentableEntity> list = this.service.selectDbTableListByNames(tableNames);
            //导入
            this.service.importGenTable(list, appId, getContext());
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
            this.doException(request, busiDesc, model, e);
        }

        ret.put(KEY_RESULT_CODE, code);
        ret.put(KEY_RESULT_DATA, model);
        return ret.toJSONString();
    }


    @PostMapping("/info")
    public String getInfo(@RequestParam(value = "tableId") Long tableId, @RequestParam(value = "appId") Long appId) {
        Map<String, Object> model = new HashMap<>();
        JSONObject ret = new JSONObject();
        String busiDesc = "查询数据库表";
        int code = VALUE_RESULT_SUCCESS;
        try {
            //查询单表信息
            GentableEntity gentableEntity = this.service.get(tableId);
            //关联查询表与列信息
            List<GentableEntity> allList = this.service.find(new GentableQuery().appId(appId)).stream().map(item->{
                List<GentableColumnEntity> columnEntities = gentableColumnService.find(new GentableColumnQuery().tableId(item.getId()));
                item.setColumns(columnEntities);
                return item;
            }).collect(Collectors.toList());


            //List<GentableEntity> allList = this.service.selectGenTableAll(appId);
            //查询列信息
            List<GentableColumnEntity> columnEntities = gentableColumnService.find(new GentableColumnQuery().tableId(tableId));
            model.put("info", gentableEntity);
            model.put("rows", columnEntities);
            model.put("tables", allList);

            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
            this.doException(request, busiDesc, model, e);
        }
        this.init(this.request, this.response, null, model, getContext());
        ret.put(KEY_RESULT_CODE, code);
        ret.put(KEY_RESULT_DATA, model);
        return ret.toJSONString();
    }

    /**
     * 通过表名生成代码
     *
     * @param tableId
     * @return
     */
    @PostMapping("/genCode")
    public void genCode(@RequestParam(value = "tableId") Long tableId,@RequestParam(value = "genTypes") String genTypes) {
        Map<String, Object> model = new HashMap<>();
        String busiDesc = "生成单表代码";
        try {

            byte[] bytes = this.service.downloadCode(tableId, genTypes);
            genCode(response, bytes);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            this.doException(request, busiDesc, model, e);
        }
    }


    /**
     * 通过表名生成代码
     *
     * @param tables
     * @return
     */
    @PostMapping("/batchGenCode")
    public void batchGenCode(@RequestParam(value = "tables") String tables,@RequestParam(value = "genTypes") String genTypes) {
        Map<String, Object> model = new HashMap<>();
        String busiDesc = "批量生成单表代码";
        try {
            Long[] tableIds = Convert.toLongArray(tables);
            byte[] bytes = this.service.downloadCode(tableIds, genTypes);
            genCode(response, bytes);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            this.doException(request, busiDesc, model, e);
        }
    }

    /**
     * 预览代码
     *
     * @param id
     * @return
     */
    @PostMapping("/preview")
    public String preview(@RequestParam(value = "id") Long id) {

        JSONObject ret = new JSONObject();
        String busiDesc = "预览代码";
        int code = VALUE_RESULT_SUCCESS;
        try {

            Map<String, String> model = this.service.previewCode(id);
            ret.put(KEY_RESULT_DATA, model);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
        }
        ret.put(KEY_RESULT_CODE, code);
        return ret.toJSONString();
    }

    /**
     * 同步数据库
     *
     * @param tableId
     * @return
     */
    @PostMapping("/synchDb")
    public String synchDb(@RequestParam(value = "tableId") Long tableId) {
        JSONObject ret = new JSONObject();
        String busiDesc = "同步数据库";
        int code = VALUE_RESULT_SUCCESS;
        try {
            this.service.synchDb(tableId);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
        }
        ret.put(KEY_RESULT_CODE, code);
        return ret.toJSONString();
    }

    /**
     * 导入文档生成代码
     *
     * @param file
     * @return
     */
    @PostMapping("/importDoc")
    public String importDoc(MultipartFile file, @RequestParam(required = false) Long appId) {
        JSONObject ret = new JSONObject();
        Map<String, Object> model = new HashMap<>();
        Context context = getContext();
        String busiDesc = "导入" + getModuleDesc();
        int code = VALUE_RESULT_SUCCESS;
        try {
            this.service.importDoc(file,appId, context);

            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
            doException(request, busiDesc, model, e);
        }
        ret.put(KEY_RESULT_CODE, code);
        ret.put(KEY_RESULT_MSG, "导入成功！");
        return ret.toJSONString();
    }


    /**
     * 导出doc
     *
     * @param projectInfo
     * @return
     */
    @PostMapping("/exportDoc")
    public void exportDoc(ProjectInfoEntity projectInfo) {
        Map<String, Object> model = new HashMap<>();
        String busiDesc = "批量导出doc文档";
        try {
            byte[] bytes = this.service.exportDoc(projectInfo);

            genCode(response, bytes);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            this.doException(request, busiDesc, model, e);
        }
    }


    /**
     * 前端动态建表
     *
     * @param tableSql
     * @return
     */
    @PostMapping("/createTableSql")
    public String createTableSql(@RequestParam(value = "tableSql") String tableSql) {
        JSONObject ret = new JSONObject();
        Map<String, Object> model = new HashMap<>();
        Context context = getContext();
        String busiDesc = "建表" + getModuleDesc();
        int code = VALUE_RESULT_SUCCESS;
        try {
            this.service.crateTableBySql(tableSql, context);

            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            code = VALUE_RESULT_FAILURE;
            doException(request, busiDesc, model, e);
        }
        ret.put(KEY_RESULT_CODE, code);
        ret.put(KEY_RESULT_MSG, model.remove(MESSAGE_INFO));
        return ret.toJSONString();
    }


    /**
     * 生成zip文件
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"genCode.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }


}