package com.yunzhupaas.base.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.base.model.ColumnDataModel;
import com.yunzhupaas.base.model.OnlineImport.VisualdevModelDataInfoVO;
import com.yunzhupaas.base.model.VisualDevJsonModel;
import com.yunzhupaas.base.model.VisualWebTypeEnum;
import com.yunzhupaas.model.OnlineDevData;
import com.yunzhupaas.onlinedev.model.*;
import com.yunzhupaas.util.NoDataSourceBind;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.entity.VisualdevEntity;
import com.yunzhupaas.base.entity.VisualdevReleaseEntity;
import com.yunzhupaas.base.entity.VisualdevShortLinkEntity;
import com.yunzhupaas.base.model.shortLink.*;
import com.yunzhupaas.base.service.VisualdevReleaseService;
import com.yunzhupaas.base.service.VisualdevService;
import com.yunzhupaas.base.service.VisualdevShortLinkService;
import com.yunzhupaas.base.util.VisualUtil;
import com.yunzhupaas.base.vo.PaginationVO;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.consts.DeviceType;
import com.yunzhupaas.database.util.TenantDataSourceUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.exception.LoginException;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.onlinedev.service.VisualDevInfoService;
import com.yunzhupaas.onlinedev.service.VisualDevListService;
import com.yunzhupaas.onlinedev.service.VisualdevModelDataService;
import com.yunzhupaas.onlinedev.util.onlineDevUtil.OnlinePublicUtils;
import com.yunzhupaas.onlinedev.util.onlineDevUtil.OnlineSwapDataUtils;
import com.yunzhupaas.util.*;
import com.yunzhupaas.util.context.RequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 在线开发表单外链Controller
 *
 * @author 云筑产品开发平台组
 * @version V3.4.2
 * @copyright 深圳市乐程软件有限公司
 * @date 2024/12/30 11:33:17
 */
@Tag(name = "表单外链" , description = "BaseShortLink" )
@RestController
@RequestMapping("/api/visualdev/ShortLink" )
public class VisualdevShortLinkController extends SuperController<VisualdevShortLinkService, VisualdevShortLinkEntity> {

    @Autowired
    private VisualdevShortLinkService visualdevShortLinkService;

    @Autowired
    private ConfigValueUtil configValueUtil;

    @Autowired
    protected AuthUtil authUtil;

    @Autowired
    private VisualdevService visualdevService;
    @Autowired
    private VisualdevReleaseService visualdevReleaseService;
    @Autowired
    private VisualdevModelDataService visualdevModelDataService;
    @Autowired
    private OnlineSwapDataUtils onlineSwapDataUtils;
    @Autowired
    private VisualDevListService visualDevListService;
    @Autowired
    private VisualDevInfoService visualDevInfoService;

    @Operation(summary = "获取外链信息" )
    @Parameters({
            @Parameter(name = "id" , description = "主键" ),
    })
    @GetMapping("/{id}" )
    @SaCheckPermission("onlineDev.webDesign" )
    public ActionResult getInfo(@PathVariable("id" ) String id) {
        VisualdevShortLinkEntity info = visualdevShortLinkService.getById(id);
        VisualdevShortLinkVo vo;
        if (info != null) {
            vo = JsonUtil.getJsonToBean(info, VisualdevShortLinkVo.class);
            vo.setAlreadySave(true);
        } else {
            vo = new VisualdevShortLinkVo();
            vo.setId(id);
        }
        vo.setFormLink(geturl(id, "form" ));
        vo.setColumnLink(geturl(id, "list" ));
        return ActionResult.success(vo);
    }

    /**
     * 获取url
     *
     * @param
     * @return
     * @copyright 深圳市乐程软件有限公司
     * @date 2023/3/9
     */
    private String geturl(String id, String type) {
        String url = configValueUtil.getApiDomain() + "/api/visualdev/ShortLink/trigger/" + id + "?encryption=";
        UserInfo userInfo = UserProvider.getUser();
        JSONObject obj = new JSONObject();
        obj.put("type" , type);
        if (configValueUtil.isMultiTenancy()) {
            obj.put("tenantId" , userInfo.getTenantId());
        }
        //参数加密
        String encryption = DesUtil.aesOrDecode(obj.toJSONString(), true,true);
        url += encryption;
        return url;
    }


    @Operation(summary = "修改外链信息" )
    @PutMapping("" )
    @SaCheckPermission("onlineDev.webDesign" )
    public ActionResult saveOrupdate(@RequestBody VisualdevShortLinkForm data) {
        VisualdevShortLinkEntity entity = JsonUtil.getJsonToBean(data, VisualdevShortLinkEntity.class);
        if(entity.getFormLink().contains(configValueUtil.getApiDomain())){
            entity.setFormLink(entity.getFormLink().replace(configValueUtil.getApiDomain(),""));
        }
        if(entity.getColumnLink().contains(configValueUtil.getApiDomain())){
            entity.setColumnLink(entity.getColumnLink().replace(configValueUtil.getApiDomain(),""));
        }
        VisualdevShortLinkEntity info = visualdevShortLinkService.getById(data.getId());
        UserInfo userInfo = UserProvider.getUser();
        if (info != null) {
            entity.setLastModifyTime(new Date());
            entity.setLastModifyUserId(userInfo.getUserId());
        } else {
            entity.setCreatorTime(new Date());
            entity.setCreatorUserId(userInfo.getUserId());
        }

        String pcLink = "/formShortLink";
        String appLink ="/pages/formShortLink/index";
        entity.setRealPcLink(pcLink);
        entity.setRealAppLink(appLink);
        entity.setUserId(userInfo.getUserId());
        visualdevShortLinkService.saveOrUpdate(entity);
        return ActionResult.success(MsgCode.SU002.get());
    }

    /**
     * 参数解密切换数据源
     *
     * @param
     * @return
     * @copyright 深圳市乐程软件有限公司
     * @date 2023/3/9
     */
    private VisualdevShortLinkModel aesDecodeMatchDatabase(String encryption) throws LoginException {
        //参数解密
        String str = DesUtil.aesOrDecode(encryption, false,true);
        if (StringUtil.isEmpty(str)) {
            throw new LoginException(MsgCode.VS009.get());
        }
        VisualdevShortLinkModel model = JsonUtil.getJsonToBean(str, VisualdevShortLinkModel.class);
        if (configValueUtil.isMultiTenancy()) {
            if (StringUtil.isNotEmpty(model.getTenantId())) {
                //切换成租户库
                TenantDataSourceUtil.switchTenant(model.getTenantId());
            } else {
                throw new LoginException(MsgCode.LOG115.get());
            }
        }
        return model;
    }

    @NoDataSourceBind
    @Operation(summary = "外链请求入口" )
    @Parameters({
            @Parameter(name = "id" , description = "主键" ),
    })
    @GetMapping("/trigger/{id}" )
    public ActionResult getlink(@PathVariable("id" ) String id,
                                @RequestParam(value = "encryption" ) String encryption,
                                HttpServletResponse response) throws LoginException, IOException {
        VisualdevShortLinkModel model = aesDecodeMatchDatabase(encryption);
        String link = "";
        VisualdevShortLinkEntity entity = visualdevShortLinkService.getById(id);
        DeviceType deviceType = UserProvider.getDeviceForAgent();
        if (entity != null) {
            if (DeviceType.PC.equals(deviceType)) {
                link = configValueUtil.getFrontDomain() + entity.getRealPcLink();
            } else {
                link =  configValueUtil.getAppDomain() + entity.getRealAppLink();
            }
        } else {
            return ActionResult.fail(MsgCode.VS010.get());
        }
        JSONObject obj = new JSONObject();
        obj.put("modelId" , id);
        obj.put("type" , model.getType());
        if (configValueUtil.isMultiTenancy()) {
            obj.put("tenantId" , model.getTenantId());
        }
        //新链接参数加密
        String encryptionNew = DesUtil.aesOrDecode(obj.toJSONString(), true,true);
        link += "?encryption=" + encryptionNew;
//        link += "&modelId=" + id;
        response.sendRedirect(link);
        return ActionResult.success(MsgCode.SU000.get());
    }

    @NoDataSourceBind
    @Operation(summary = "获取外链配置" )
    @Parameters({
            @Parameter(name = "id" , description = "主键" ),
    })
    @GetMapping("/getConfig/{id}" )
    public ActionResult getConfig(@PathVariable("id" ) String id, @RequestParam("encryption" ) String encryption) throws LoginException {
        aesDecodeMatchDatabase(encryption);

        VisualdevShortLinkEntity info = visualdevShortLinkService.getById(id);
        VisualdevShortLinkConfigVo vo = JsonUtil.getJsonToBean(info, VisualdevShortLinkConfigVo.class);
        vo.setFormLink(geturl(id, "form" ));
        vo.setColumnLink(geturl(id, "list" ));
        return ActionResult.success(vo);
    }

    @NoDataSourceBind
    @Operation(summary = "密码验证" )
    @PostMapping("/checkPwd" )
    public ActionResult checkPwd(@RequestBody VisualdevShortLinkPwd form) throws LoginException {
        //参数解密
        VisualdevShortLinkModel model = aesDecodeMatchDatabase(form.getEncryption());

        VisualdevShortLinkEntity info = visualdevShortLinkService.getById(form.getId());
        boolean flag = false;
        if (OnlineDevData.STATE_ENABLE.equals(info.getFormPassUse()) && 0 == form.getType()) {
            if (Md5Util.getStringMd5(info.getFormPassword()).equals(form.getPassword())) {
                flag = true;
            }
        } else if (OnlineDevData.STATE_ENABLE.equals(info.getColumnPassUse()) && 1 == form.getType()) {
            if (Md5Util.getStringMd5(info.getColumnPassword()).equals(form.getPassword())) {
                flag = true;
            }
        }
        if (flag) {
            return ActionResult.success();
        }
        return ActionResult.fail(MsgCode.VS011.get());
    }

    @NoDataSourceBind
    @Operation(summary = "获取列表表单配置JSON" )
    @GetMapping("/{modelId}/Config" )
    public ActionResult getData(@PathVariable("modelId" ) String modelId, @RequestParam(value = "type" , required = false) String type,
                                @RequestParam("encryption" ) String encryption) throws WorkFlowException, LoginException {
        aesDecodeMatchDatabase(encryption);
        VisualdevEntity entity;
        //线上版本
        if ("0".equals(type)) {
            entity = visualdevService.getInfo(modelId);
        } else {
            VisualdevReleaseEntity releaseEntity = visualdevReleaseService.getById(modelId);
            entity = JsonUtil.getJsonToBean(releaseEntity, VisualdevEntity.class);
        }
        if (entity == null) {
            return ActionResult.fail(MsgCode.VS012.get());
        }

        String s = VisualUtil.checkPublishVisualModel(entity, MsgCode.VS005.get());
        if (s != null) {
            return ActionResult.fail(s);
        }
        DataInfoVO vo = JsonUtil.getJsonToBean(entity, DataInfoVO.class);
        return ActionResult.success(vo);
    }

    @NoDataSourceBind
    @Operation(summary = "外链数据列表" )
    @Parameters({
            @Parameter(name = "modelId" , description = "模板id" ),
    })
    @PostMapping("/{modelId}/ListLink" )
    public ActionResult ListLink(@PathVariable("modelId" ) String modelId, @RequestParam("encryption" ) String encryption,
                                 @RequestBody PaginationModel paginationModel) throws WorkFlowException, LoginException {
        aesDecodeMatchDatabase(encryption);

        VisualdevReleaseEntity visualdevEntity = visualdevReleaseService.getById(modelId);
        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);
        //判断请求客户端来源
        if (!RequestContext.isOrignPc()) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }
        List<Map<String, Object>> realList;
        if (VisualWebTypeEnum.DATA_VIEW.getType().equals(visualdevEntity.getWebType())) {//
            //数据视图的接口数据获取、
            ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(), ColumnDataModel.class);
            realList = onlineSwapDataUtils.getInterfaceData(visualdevEntity, paginationModel, columnDataModel);
        } else {
            realList = visualDevListService.getDataListLink(visualJsonModel, paginationModel);
        }
        PaginationVO paginationVO = JsonUtil.getJsonToBean(paginationModel, PaginationVO.class);
        return ActionResult.page(realList, paginationVO);
    }

    @NoDataSourceBind
    @Operation(summary = "获取数据信息(带转换数据)" )
    @Parameters({
            @Parameter(name = "modelId" , description = "模板id" ),
            @Parameter(name = "id" , description = "数据id" ),
    })
    @GetMapping("/{modelId}/{id}/DataChange" )
    public ActionResult infoWithDataChange(@PathVariable("modelId" ) String modelId, @PathVariable("id" ) String id,
                                           @RequestParam("encryption" ) String encryption) throws DataException, ParseException, IOException, SQLException, LoginException {
        aesDecodeMatchDatabase(encryption);

        modelId = XSSEscape.escape(modelId);
        id = XSSEscape.escape(id);
        VisualdevEntity visualdevEntity = visualdevService.getReleaseInfo(modelId);
        //有表
        if (!StringUtil.isEmpty(visualdevEntity.getVisualTables()) && !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getVisualTables())) {
            VisualdevModelDataInfoVO vo = visualDevInfoService.getDetailsDataInfo(id, visualdevEntity);
            return ActionResult.success(vo);
        }
        //无表
        VisualdevModelDataInfoVO vo = visualdevModelDataService.infoDataChange(id, visualdevEntity);
        return ActionResult.success(vo);
    }

    //**********以下微服务和单体不同
    @NoDataSourceBind
    @Operation(summary = "添加数据" )
    @Parameters({
            @Parameter(name = "modelId" , description = "模板id" ),
            @Parameter(name = "visualdevModelDataCrForm" , description = "功能数据创建表单" ),
    })
    @PostMapping("/{modelId}" )
    public ActionResult create(@PathVariable("modelId" ) String modelId, @RequestParam("encryption" ) String encryption,
                               @RequestBody VisualdevModelDataCrForm visualdevModelDataCrForm) throws WorkFlowException, LoginException {
        VisualdevShortLinkModel visualdevShortLinkModel = aesDecodeMatchDatabase(encryption);
        VisualdevShortLinkEntity info = visualdevShortLinkService.getById(modelId);
        if (1 != info.getFormUse()) {
            return ActionResult.fail(MsgCode.VS013.get());
        }
        String tenantId=visualdevShortLinkModel.getTenantId();
        try {
            if (configValueUtil.isMultiTenancy()) {
                if (StringUtil.isNotEmpty(tenantId)) {
                    //切换成租户库
                    TenantDataSourceUtil.switchTenant(tenantId);
                } else {
                    return ActionResult.fail(MsgCode.LOG115.get());
                }
            }
            VisualdevEntity visualdevEntity = visualdevService.getReleaseInfo(modelId);
            Map<String, Object> map = JsonUtil.stringToMap(visualdevModelDataCrForm.getData());
            visualdevModelDataService.visualCreate(VisualParamModel.builder().visualdevEntity(visualdevEntity).data(map).isLink(true).build());
        }catch (Exception e){
            throw new WorkFlowException(e.getMessage(), e);
        }
        return ActionResult.success(MsgCode.SU001.get());
    }
}

