package com.yunzhupaas.generater.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.xuyanwu.spring.file.storage.FileInfo;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.entity.DictionaryDataEntity;
import com.yunzhupaas.base.entity.VisualdevEntity;
import com.yunzhupaas.base.entity.VisualdevReleaseEntity;
import com.yunzhupaas.base.model.DownloadCodeForm;
import com.yunzhupaas.base.model.VisualAliasForm;
import com.yunzhupaas.base.model.read.ReadListVO;
import com.yunzhupaas.base.model.read.ReadModel;
import com.yunzhupaas.base.service.DictionaryDataService;
import com.yunzhupaas.base.service.VisualAliasService;
import com.yunzhupaas.base.service.VisualdevReleaseService;
import com.yunzhupaas.base.service.VisualdevService;
import com.yunzhupaas.base.util.ReadFile;
import com.yunzhupaas.base.util.VisualUtil;
import com.yunzhupaas.base.vo.DownloadVO;
import com.yunzhupaas.base.vo.ListVO;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.constant.FileTypeConstant;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.generater.service.VisualdevGenService;
import com.yunzhupaas.model.visualJson.TableModel;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 可视化开发功能表
 *
 * @author 云筑产品开发平台组
 * @version V3.1.0
 * @copyright 深圳市乐程软件有限公司（http://www.szlecheng.cn）
 * @date 2024/3/16
 */
@Tag(name = "代码生成器", description = "Generater")
@RestController
@RequestMapping("/api/visualdev/Generater")
public class VisualdevGenController {

    @Autowired
    private ConfigValueUtil configValueUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private VisualdevService visualdevService;
    @Autowired
    private VisualdevReleaseService visualdevReleaseService;
    @Autowired
    private VisualdevGenService visualdevGenService;
    @Autowired
    private DictionaryDataService dictionaryDataApi;
    @Autowired
    private VisualAliasService aliasService;


    /**
     * 下载文件
     *
     * @return
     */
    @NoDataSourceBind()
    @Operation(summary = "下载文件")
    @GetMapping("/DownloadVisCode")
    public void downloadCode() throws DataException {
        HttpServletRequest request = ServletUtil.getRequest();
        String reqJson = request.getParameter("encryption");
        String name = request.getParameter("name");
        String fileNameAll = DesUtil.aesDecode(reqJson);
        if (!StringUtil.isEmpty(fileNameAll)) {
            String token = fileNameAll.split("#")[0];
            if (TicketUtil.parseTicket(token) != null) {
                TicketUtil.deleteTicket(token);
                String fileName = fileNameAll.split("#")[1];
                String path = FilePathUtil.getFilePath(FileTypeConstant.CODETEMP);
                //下载到本地
                byte[] bytes = FileUploadUtils.downloadFileByte(path, fileName, false);
                FileDownloadUtil.downloadFile(bytes, fileName, name);
                //删除打包的临时文件，释放存储
                FileUploadUtils.deleteFileByPathAndFileName(path, fileName);
            } else {
                throw new DataException(MsgCode.VS014.get());
            }
        } else {
            throw new DataException(MsgCode.VS014.get());
        }
    }

    @Operation(summary = "获取命名空间")
    @GetMapping("/AreasName")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    public ActionResult getAreasName() {
        String areasName = configValueUtil.getCodeAreasName();
        List<String> areasNameList = new ArrayList(Arrays.asList(areasName.split(",")));
        return ActionResult.success(areasNameList);
    }

    @Operation(summary = "下载代码")
    @Parameters({
            @Parameter(name = "id", description = "主键"),
    })
    @PostMapping("/{id}/Actions/DownloadCode")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    @DSTransactional
    public ActionResult downloadCode(@PathVariable("id") String id, @RequestBody DownloadCodeForm downloadCodeForm) throws Exception {
        if (downloadCodeForm.getModule() != null) {
            DictionaryDataEntity info = dictionaryDataApi.getInfo(downloadCodeForm.getModule());
            if (info != null) {
                downloadCodeForm.setModule(info.getEnCode());
            }
        }
        VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(visualdevReleaseService.getById(id), VisualdevEntity.class);
        String s = VisualUtil.checkPublishVisualModel(visualdevEntity, MsgCode.VS006.get());
        if (s != null) {
            return ActionResult.fail(s);
        }
        DownloadVO vo;
        String fileName = visualdevGenService.codeGengerateV3(visualdevEntity, downloadCodeForm);

        //服务器生成路径
        String filePath = FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + fileName + ".zip";
        FileUtil.toZip(filePath, true, FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + fileName);
        // 删除源文件
        FileUtil.deleteFileAll(new File(FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + fileName));

        //上传压缩包到服务器
        MultipartFile multipartFile = FileUtil.createFileItem(new File(XSSEscape.escapePath(filePath)));
        FileInfo fileInfo = FileUploadUtils.uploadFile(multipartFile, configValueUtil.getServiceDirectoryPath(), fileName + ".zip");
        // 删除压缩包
        FileUtil.deleteFileAll(new File(filePath));
        //下载文件服务器上的压缩包
        vo = DownloadVO.builder().name(fileInfo.getFilename()).url(UploaderUtil.uploaderVisualFile(fileInfo.getFilename()) + "&name=" + fileName + ".zip").build();
        if (vo == null) {
            return ActionResult.fail(MsgCode.FA006.get());
        }
        return ActionResult.success(vo);
    }


    /**
     * 输出移动开发模板
     *
     * @return
     */
    @Operation(summary = "预览代码")
    @Parameters({
            @Parameter(name = "id", description = "主键"),
    })
    @PostMapping("/{id}/Actions/CodePreview")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    public ActionResult codePreview(@PathVariable("id") String id, @RequestBody DownloadCodeForm downloadCodeForm) throws Exception {
        if (downloadCodeForm.getModule() != null) {
            DictionaryDataEntity info = dictionaryDataApi.getInfo(downloadCodeForm.getModule());
            if (info != null) {
                downloadCodeForm.setModule(info.getEnCode());
            }
        }
        VisualdevReleaseEntity releaseEntity = visualdevReleaseService.getById(id);
        VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(releaseEntity, VisualdevEntity.class);
        String s = VisualUtil.checkPublishVisualModel(visualdevEntity, "预览");
        if (s != null) {
            return ActionResult.fail(s);
        }
        String fileName = visualdevGenService.codeGengerateV3(visualdevEntity, downloadCodeForm);

        List<ReadListVO> dataList = ReadFile.priviewCode(FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + fileName);
        // 删除源文件
        FileUtil.deleteFileAll(new File(FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + fileName));
        if (dataList.size() == 0) {
            return ActionResult.fail(MsgCode.FA015.get());
        }

        //代码对比
        if (downloadCodeForm.isContrast()) {
            VisualdevEntity oldEntity = visualdevService.getInfo(id);
            //修改状态 - 旧的是已发布，新的是草稿版本；发布状态 - 旧的是 旧的发布版本，新的是当前发布版本；
            boolean statusUpdate = true;
            if (Objects.equals(oldEntity.getState(), 1) && StringUtil.isNotBlank(releaseEntity.getOldContent())) {
                statusUpdate = false;
                VisualdevEntity jsonToBean = JsonUtil.getJsonToBean(releaseEntity.getOldContent(), VisualdevEntity.class);
                oldEntity.setVisualTables(jsonToBean.getVisualTables());
                oldEntity.setFormData(jsonToBean.getFormData());
                oldEntity.setColumnData(jsonToBean.getColumnData());
                oldEntity.setAppColumnData(jsonToBean.getAppColumnData());
                oldEntity.setWebType(jsonToBean.getWebType());
                oldEntity.setDbLinkId(jsonToBean.getDbLinkId());
            }

            String oldFileName = visualdevGenService.codeGengerateV3(oldEntity, downloadCodeForm);
            List<ReadListVO> oldDataList = ReadFile.priviewCode(FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + oldFileName);
            // 删除源文件
            FileUtil.deleteFileAll(new File(FileUploadUtils.getLocalBasePath() + configValueUtil.getServiceDirectoryPath() + oldFileName));

            for (ReadListVO m : dataList) {
                ReadListVO n = oldDataList.stream().filter(t -> m.getFileName().equals(t.getFileName())).findFirst().orElse(null);
                if (Objects.nonNull(n)) {
                    List<ReadModel> mChildren = m.getChildren();
                    List<ReadModel> nChildren = n.getChildren();
                    for (ReadModel mChild : mChildren) {
                        ReadModel nChild = nChildren.stream().filter(t -> mChild.getFileName().equals(t.getFileName())).findFirst().orElse(null);
                        String nfileContent = Objects.nonNull(nChild) ? nChild.getFileContent() : "";
                        if (statusUpdate) {
                            mChild.setOldFileContent(mChild.getFileContent());
                            mChild.setFileContent(nfileContent);
                        } else {
                            mChild.setOldFileContent(nfileContent);
                        }
                    }
                }
            }
        }

        ListVO datas = new ListVO<>();
        datas.setList(dataList);
        return ActionResult.success(datas);
    }

    /**
     * App预览(后台APP表单设计)
     *
     * @return
     */
    @Operation(summary = "App预览(后台APP表单设计)")
    @Parameters({
            @Parameter(name = "data", description = "数据"),
    })
    @PostMapping("/App/Preview")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    public ActionResult appPreview(String data) {
        String id = RandomUtil.uuId();
        redisUtil.insert(id, data, 300);
        return ActionResult.success((Object) id);
    }

    /**
     * App预览(后台APP表单设计)
     *
     * @return
     */
    @Operation(summary = "App预览查看")
    @Parameters({
            @Parameter(name = "id", description = "主键"),
    })
    @GetMapping("/App/{id}/Preview")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    public ActionResult preview(@PathVariable("id") String id) {
        if (redisUtil.exists(id)) {
            Object object = redisUtil.getString(id);
            return ActionResult.success(object);
        } else {
            return ActionResult.fail(MsgCode.FA019.get());
        }
    }

    @Operation(summary = "获取命名规范")
    @Parameters({
            @Parameter(name = "id", description = "主键"),
    })
    @GetMapping("/{id}/Alias/Info")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    public ActionResult getAliasInfo(@PathVariable("id") String id) {
        List<TableModel> aliasInfo = aliasService.getAliasInfo(id);
        return ActionResult.success(aliasInfo);
    }

    @Operation(summary = "命名规范保存")
    @Parameters({
            @Parameter(name = "id", description = "主键"),
    })
    @PostMapping("/{id}/Alias/Save")
    @SaCheckPermission(value = {"onlineDev.webDesign", "generator.webForm", "generator.flowForm"}, mode = SaMode.OR)
    public ActionResult aliasSave(@PathVariable("id") String id, @RequestBody VisualAliasForm form) {
        aliasService.aliasSave(id, form);
        return ActionResult.success(MsgCode.SU002.get());
    }
}

