package com.yh.saas.platform.controller;

import ch.qos.logback.classic.Logger;
import com.alibaba.fastjson.JSONObject;
import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.winsea.svc.base.base.entity.CommonAppendix;
import com.winsea.svc.base.base.service.IAppendixService;
import com.winsea.svc.base.base.util.AppendixWrapper;
import com.winsea.svc.base.base.util.ClientTypeChecker;
import com.winsea.svc.base.base.util.DateUtils;
import com.winsea.svc.base.base.view.CommonAppendixView;
import com.winsea.svc.base.security.util.AuthSecurityUtils;
import com.yh.saas.platform.util.GtAppendixUtil;
import com.yh.saas.plugin.yiliangyiyun.util.GeneratorUtil;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.util.Streams;
import org.apache.velocity.shaded.commons.io.FilenameUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 附件表 前端控制器
 * </p>
 *
 * @author zhaojz
 * @since 2019-03-25
 */
@RestController
@RequestMapping("/appendix")
public class AppendixController implements InitializingBean {

    private Logger log = (Logger) LoggerFactory.getLogger(this.getClass());

    private static final String FILE_SEPERATOR = "/";

    @SofaReference
    private IAppendixService appendixService;

    @Autowired
    private AppendixWrapper appendixWrapper;

    @Value("${file-root-path}")
    private String fileRootPath;

    @Value("${front-origin}")
    private String frontOrigin;

    @Getter
    @Value("${oss.bucket.name:}")
    private String bucketName;

    @Getter
    @Value("${oss.endpoint.default:}")
    private String endpoint;

    @Value("${server.port:}")
    private String port;

    @Value("${oss.isUsed:true}") // 默认使用OSS存储 即使不在.properties配置 默认是true
    private boolean isOssUsed;

    static final String LOCAL_PERFIX_URL = "http://127.0.0.1:{0}/";

    static final String OSS_PERFIX_URL = "https://{0}.{1}/";

    private String host;

    @Getter
    @Value("${oss.endpoint.internal:}")
    private String baseUrl;
    @Autowired
    private OSSClient ossClient;
    @Override
    public void afterPropertiesSet() throws Exception {
        host = "http://" + bucketName + "." + endpoint;
    }
    /**
     * 查询附件
     * @return
     */
    @GetMapping("/query/getFileList")
    public List<CommonAppendix> getFileList(@RequestParam String appendixIds) {
        List<CommonAppendix> list = appendixService.selectBatchIds(Arrays.asList(appendixIds.split(",")));
        return list;
    }

    /**
     * 批量下载附件
     */
    @GetMapping("/download/batchAttachment")
    public void batchDownload(@RequestParam String appendixIds, @RequestParam String zipName) {
        List<String> appendixIdList = new ArrayList<>();
        if (appendixIds.contains(",")) {
            appendixIdList = Arrays.asList(appendixIds.split(","));
        } else {
            appendixIdList.add(appendixIds);
        }
        List<CommonAppendix> appendices = this.appendixService.getAppendixs(appendixIdList);
        appendixWrapper.packAndDownloadByIdList(appendices, zipName);
    }

    /**
     * 保存附件
     *
     * @return
     */
    @PostMapping("/api/saveFiles")
    public List<String> saveFiles(@RequestBody CommonAppendixView appendixView) {
        if (CollectionUtils.isNotEmpty(appendixView.getNewAppendixs())) {
            String compId = AuthSecurityUtils.getCurrentUserInfo().getCompId();
            appendixView.getNewAppendixs().stream().forEach(appendix -> appendix.setCompId(compId));
        }
        return appendixService.saveFiles(appendixView.getNewAppendixs(), appendixView.getOldAppendixIds());
    }

    /**
     * 删除附件
     *
     * @return
     */
    @PostMapping("/api/deleteFiles")
    public void deleteFiles(String appendixIds) {
        if (StringUtils.isNotBlank(appendixIds)) {
            appendixService.deleteBatchIds(Arrays.asList(appendixIds.split(",")));
        }
    }

    /**
     * 关联附件
     *
     * @param appendixIds
     * @param modelId
     * @return
     */
    @PostMapping("/api/relateFiles")
    public void relateFiles(String appendixIds, String modelId) {
        appendixService.relateAppendixs(appendixIds, modelId);
    }

    /**
     * 单个附件下载
     *
     * @param request
     * @param response
     */
    @GetMapping("/api/singleDownLoadFile")
    public HttpServletResponse singleDownLoadFile(HttpServletRequest request, HttpServletResponse response) {
        String appendixId = request.getParameter("appendixId");
        return getCommonAppendixOutputStream(request, response, appendixId);
    }

    public HttpServletResponse getCommonAppendixOutputStream(HttpServletRequest request, HttpServletResponse response, String appendixId) {
        try {
            List<File> fileList = new ArrayList<>();
            CommonAppendix appendixs = appendixService.selectById(appendixId);
            // path是指欲下载的文件的路径。
            File file = new File(fileRootPath + URLDecoder.decode(appendixs.getAppendixPath(), String.valueOf(StandardCharsets.UTF_8)));
            // 取得文件名。
            String filename = appendixs.getAppendixName();

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(fileRootPath + URLDecoder.decode(appendixs.getAppendixPath(), String.valueOf(StandardCharsets.UTF_8))));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(StandardCharsets.UTF_8), "ISO8859-1"));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            log.error("下载失败", ex);
        }
        return response;
    }


    /**
     * 上传附件
     *
     * @param request
     * @return
     */
    @PostMapping("/api/uploadFiles")
    public Object uploadFiles(HttpServletRequest request) {
        List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("fileName");
        if (files.isEmpty()) {
            return null;
        }
        String companyId = request.getParameter("companyId");
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();
            fileName = fileName.substring(0, fileName.lastIndexOf("."));
            try {
                CommonAppendix appendix = new CommonAppendix();
                appendix.setAppendixName(
                        fileName + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
                String path = upload(file,file.getOriginalFilename(),companyId);
                appendix.setAppendixPath(path);
                int size = (int) file.getSize();
                appendix.setAppendixSize(GtAppendixUtil.getFileSize(size));
                log.info("文件上传成功 地址：", path);
                return appendix;
            } catch (Exception e) {
                log.error("文件上传失败", e.toString());
            }
            finally {
//                dest.delete();
            }
        }
        return null;
    }

    /**
     * 打包下载附件
     *
     * @param request
     * @param response
     */
    @PostMapping("/api/downLoadFiles")
    public void downLoadFiles(HttpServletRequest request, HttpServletResponse response) {
        String billId = request.getParameter("billId");
        try {
            if (StringUtils.isBlank(frontOrigin)) {
                response.getWriter().print(JSONObject.toJSON(this.getPrintJson("noPermission")));
                return;
            }
            String[] allowDomain = frontOrigin.split(",");
            String requestOrigin = request.getHeader("Origin");
            Set<String> allowedOrigins = new HashSet<>(Arrays.asList(allowDomain));
            if (!allowedOrigins.contains(requestOrigin)) {
                response.getWriter().print(JSONObject.toJSON(this.getPrintJson("noPermission")));
                return;
            }
            List<File> fileList = new ArrayList<>();
            List<CommonAppendix> appendixs = this.selectAppendixList(billId);
            // 添加前缀
            addPrefix(appendixs);
            if (CollectionUtils.isEmpty(appendixs) || StringUtils.isBlank(frontOrigin)) {
                response.getWriter().print(JSONObject.toJSON(this.getPrintJson("noFileData")));
                return;
            }
            for (CommonAppendix appendix : appendixs) {
                File file = new File(fileRootPath + File.separator + appendix.getAppendixPath());
                if (!file.exists()) {
                    continue;
                }
                fileList.add(file);
            }
            File rootFile = new File(fileRootPath + File.separator + "tempFile.zip");
            if (!rootFile.exists()) {
                boolean result = rootFile.createNewFile();
                if (!result) {
                    log.warn(rootFile.getAbsolutePath() + "创建失败！");
                }
            }
            // 创建文件输出流
            try (FileOutputStream fous = new FileOutputStream(rootFile);
                 ZipOutputStream zipOut = new ZipOutputStream(fous)) {
                GtAppendixUtil.zipFiles(fileList, zipOut);
                GtAppendixUtil.downloadZip(rootFile, requestOrigin, response);
            }
        } catch (Exception e) {
            log.error("文删除失败", e);
        }
    }

    /**
     * 查询要打包的附件
     *
     * @param billIds
     * @return
     */
    private List<CommonAppendix> selectAppendixList(String billIds) {
        String[] billIdArr = billIds.split(",");
        List<CommonAppendix> appendixs = new ArrayList<>();
        for (String billId : billIdArr) {
            Wrapper<CommonAppendix> wrapper = new EntityWrapper<CommonAppendix>().eq("delete_flag", "0").eq("bill_id",
                    billId);
            List<CommonAppendix> dataList = appendixService.selectList(wrapper);
            if (!CollectionUtils.isEmpty(dataList)) {
                appendixs.addAll(dataList);
            }
        }
        return appendixs;
    }

    private Map<String, String> getPrintJson(String dataMsg) {
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("code", String.valueOf(HttpServletResponse.SC_OK));
        resultMap.put("data", dataMsg);
        resultMap.put("message", "Success");
        return resultMap;
    }

    /**
     * 添加前缀
     *
     * @param list
     */
    private void addPrefix(List<CommonAppendix> list) {
        if (ClientTypeChecker.isLandBased()) {
            String prefixUrl = MessageFormat.format(OSS_PERFIX_URL, bucketName, endpoint);
            list.stream().filter(appendix -> !StringUtils.startsWith(appendix.getAppendixPath(), "http"))
                    .forEach(appendix -> appendix.setAppendixPath(prefixUrl + appendix.getAppendixPath()));
        }
    }
    /**
     * 后台通过服务器间接传文件
     * @param file
     * @return
     * @throws IOException
     */
    public  String upload(MultipartFile file,String name,String companyId) throws IOException {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(file.getSize());
        objectMetadata.setContentType(file.getContentType());
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, "eliangeyun/"+companyId+"/" +name, file.getInputStream(), objectMetadata);
        ossClient.putObject(putObjectRequest);
        return baseUrl + "eliangeyun/" +companyId+"/" +name;
    }
}
