package com.search.supersearch.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.search.supersearch.common.R;
import com.search.supersearch.model.FileInfo;
import com.search.supersearch.model.PreviewInfo;
import com.search.supersearch.model.UserInfo;
import com.search.supersearch.model.pojo.DocsIndex;
import com.search.supersearch.service.EsService;
import com.search.supersearch.service.OssService;
import com.search.supersearch.util.WpsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.http.Header;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@RestController
@RequestMapping("/wps")
@Slf4j
@Api(value = "wps数据预览", tags = "wps数据预览接口")
public class WPSController {

    @Autowired
    private EsService esService;

    @Value("${wps.api.url}")
    private String url;
    @Value("${wps.v2.url}")
    private String urlv2;

    @Value("${wps.appId}")
    private String appId;

    @Value("${wps.appKey}")
    private String appKey;
    @Value("${wps.downloadFile}")
    private String downloadFile;
    @Value("${oss.bucketName}")
    private String bucketName;
    @Value("${wps.v2.ak}")
    private String ak;
    @Value("${wps.v2.sk}")
    private String sk;
    @Resource
    private OssService ossService;

    @RequestMapping({"/callback/v1/3rd/file/info", "/preview/callback", "/callback"})
    @SneakyThrows
    @ApiOperation("回调地址")
    public PreviewInfo gettika3(@RequestParam(required = false) Map<String, Object> params) {
        log.info("wps回调接口,参数={}", params);
        PreviewInfo previewInfo = new PreviewInfo();
        String fileId = null;
        if (params.containsKey("_w_third_file_id")) {
            fileId = params.get("_w_third_file_id").toString();
            log.info("文件 id：" + fileId);
        }
        if (StrUtil.isEmpty(fileId)) {
            previewInfo.setResult(10001);
            previewInfo.setMsg("文件 id 为空");
            log.info("状态码标识={},错误信息={}", 10001, "文件 id 为空");
            return previewInfo;
        }
        DocsIndex docFile = esService.getByFileId(fileId);
        if (docFile == null) {
            previewInfo.setResult(10001);
            previewInfo.setMsg("未查询到文件信息");
            log.info("状态码标识={},错误信息={}", 10001, "未查询到文件信息");
            return previewInfo;
        }
        FileInfo file = new FileInfo();
        UserInfo user = new UserInfo();
        file.setId(fileId);

        String ossFileFullPath = docFile.getData().get("ossFileFullPath") + "";

        file.setName(docFile.getEs_fileId()+docFile.getData().get("fileExtension"));
        file.setVersion(1);
        file.setSize(Long.parseLong(docFile.getData().get("metaFilesize") + ""));
        file.setCreator("id0");
        file.setCreateTime(1136185445L);
        file.setModifier("id1000");
        file.setModifyTime(1551409818L);
        log.info("downloadFile1={}", downloadFile + docFile.getEs_fileId());
        file.setDownloadUrl(downloadFile + docFile.getEs_fileId());

        file.setPreview_pages(0);
        user.setId("id1000");
        user.setName("wps-1000");
        user.setPermission("read");
        user.setAvatarUrl("https://dsjsj.elinkpoc.spic.com.cn/img/pic-banner.bf296ad0.png");
        previewInfo.setFile(file);
        previewInfo.setUserInfo(user);
        previewInfo.setResult(200);
        // 如果报错则返回一下接口
        log.info("wps回调接口,返回的数据={}", JSONUtil.parseObj(previewInfo));
        return previewInfo;
    }

    /**
     * 获取预览 url
     */
    @GetMapping("/downloadFile")
    @ApiOperation("获取wps数据预览url")
    @SneakyThrows
    public void downloadFile(@RequestParam(required = false) String fileid, HttpServletResponse response) {
        log.info("wps 下载文件接口, 接口参数：" + fileid);
        DocsIndex docsIndex = esGetFileInfo(fileid);
        log.info("docsIndex={}", docsIndex);
        File file = ossGetFile(docsIndex.getEs_file_path());
//        File file =new File("/Users/wangrui/Downloads/国家现行规范国家标准目录.doc");

        byte[] data = Files.readAllBytes(file.toPath());
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + docsIndex.getData().get("ossFileFullPath"));
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(data);
        outputStream.flush();

        if (file.exists()) {
            file.delete();
        }
        log.info("wps 下载文件接口,结束");
    }

    @SneakyThrows
    private File ossGetFile(String objectName) {
        URL ossObjectUrl = ossService.getOssObjectUrl(objectName, ossService.restOSSClient());
        File file = new File("./tmp_down/tmp_" + IdUtil.fastSimpleUUID());
        FileUtils.copyURLToFile(ossObjectUrl, file);
        return file;
    }

    @SneakyThrows
    private DocsIndex esGetFileInfo(String fileid) {
        return esService.getByFileId(fileid);
    }

    /**
     * 获取预览 url
     */
    @GetMapping("/preview/url")
    @ApiOperation("获取wps数据预览url")
    public R<?> getPreviewUrl(@RequestParam(required = false) String fileid) {
        log.info("wps 请求预览地址,参数={}", fileid);
        String appToken = getToken();
        if (StrUtil.isEmpty(appToken)) {
            return R.fail("appToken 为空");
        }
        // TODO 从数据库获取文件 id
        String body = null;
        String sceneId = UUID.randomUUID().toString().replace("-", "");
        String contentMd5 = DigestUtil.md5Hex(Optional.ofNullable(body).orElse(""));
        String dateStr = ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneId.of("GMT")));
        String urls = "/preview/v2/url?app_token=" + appToken + "&file_id=" + fileid + "&scene_id=" + sceneId;
        // 处理请求头
        String xAuth = String.format("WPS-3:%s:%s", appId, DigestUtil.sha1Hex(appKey + contentMd5 + urls + "application/json" + dateStr));
//        String xAuth = WpsUtil.configOpendocAPIHeader_WPS4(appKey,null,urls,urls);
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-type", "application/json");
        headers.put("X-Auth", xAuth);
        headers.put("Date", dateStr);
        headers.put("Content-Md5", contentMd5);

        String requestUrl = url + "/preview/v2/url?app_token=" + appToken + "&file_id=" + fileid + "&scene_id=" + sceneId;
        log.info("请求中台获取预览数据url的请求路径为：" + requestUrl);
        log.info("请求中台预览数据URL的请求头：" + headers);
        String response = HttpUtil.createGet(requestUrl).addHeaders(headers).execute().body();
        log.info("获取到的预览数据 url 的返回值：" + response);
        if (StrUtil.isEmpty(response)) {
            return R.fail("获取预览url数据为空");
        }
        JSONObject json = JSONUtil.parseObj(response);
        if (json.containsKey("url")) {
            json.set("token", appToken);
            return R.data(json);
        } else {
            return R.fail("获取预览url出错");
        }
    }

    /**
     * 获取预览 url
     */
    @GetMapping("/preview/url/v2")
    @ApiOperation("获取wps数据预览url2")
    public R<?> getPreviewUrlV2(@RequestParam(required = false) String fileid) {

        String urls = "/preview/v2/url?" + "file_id=" + fileid;
        // 处理请求头
        List<Header> headers = WpsUtil.configOpendocAPIHeader_WPS4(ak, sk, urls, urls, "GET");
        Map<String, String> hm = new HashMap<>();
        headers.forEach(v -> hm.put(v.getName(), v.getValue()));
        String requestUrl = urlv2 + urls;
        log.info("请求中台获取预览数据url的请求路径为：" + requestUrl);
        log.info("请求中台预览数据URL的请求头：" + headers);
        String response = HttpUtil.createGet(requestUrl).addHeaders(hm).execute().body();
        log.info("获取到的预览数据 url 的返回值：" + response);
        if (StrUtil.isEmpty(response)) {
            return R.fail("获取预览url数据为空");
        }
        JSONObject json = JSONUtil.parseObj(response);
        if (json.containsKey("url")) {
            return R.data(json);
        } else {
            return R.fail("获取预览url出错");
        }
    }

    /**
     * 获取应用token
     */
    private String getToken() {
        String appToken = "";
        String urls = String.format("/auth/v1/app/inscope/token?app_id=%s&scope=%s", appId, "file_preview");
        String body = null;
        String contentMd5 = DigestUtil.md5Hex(Optional.ofNullable(body).orElse(""));
        String dateStr = ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneId.of("GMT")));
        String xAuth = String.format("WPS-3:%s:%s", appId, DigestUtil.sha1Hex(appKey + contentMd5 + urls + "application/json" + dateStr));
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-type", "application/json");
        headers.put("X-Auth", xAuth);
        headers.put("Date", dateStr);
        headers.put("Content-Md5", contentMd5);
        String requestUrl = url + urls;
        log.info("请求路径：" + requestUrl);
        log.info("请求头参数：" + headers);
        String response = HttpUtil.createGet(requestUrl).addHeaders(headers).execute().body();
        log.info("获取到的返回值：" + response);
        if (StrUtil.isNotEmpty(response)) {
            JSONObject jsonObject = JSONUtil.parseObj(response);
            if (jsonObject.containsKey("token")) {
                Object obj = jsonObject.get("token");
                JSONObject json = JSONUtil.parseObj(obj);
                appToken = json.getStr("app_token");
            }
        }
        log.info("获取的token为：" + appToken);
        return appToken;
    }

}
