package com.ywt.outpatient.service.common;

import com.google.protobuf.ByteString;
import com.ywt.biz.common.util.Checksum;
import com.ywt.biz.common.util.StringHelper;
import com.ywt.gapi.base.file.*;
import com.ywt.gapi.base.wechat.GetAccessTokenRequest;
import com.ywt.gapi.base.wechat.GetAccessTokenResponse;
import com.ywt.gapi.base.wechat.WeChatService;
import com.ywt.outpatient.core.Constant;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

@Service
public class FileProvider {
    private static Logger logger = LoggerFactory.getLogger(FileProvider.class);

    @DubboReference
    private FileService fileServiceBlockingStub;

    @DubboReference
    private WeChatService weChatServiceBlockingStub;

    /**
     * 上传图片
     *
     * @param filename
     * @param path
     * @param bytes
     * @return
     */
    public String uploadImage(String filename, String path, byte[] bytes) {
        UploadImageRequest req = UploadImageRequest.newBuilder()
                .setFilename(filename)
                .setDatas(ByteString.copyFrom(bytes))
                .setVpath(path)
                .build();
        UploadImageResponse res = fileServiceBlockingStub.uploadImage(req);

        return res.getCode() == 0 ? res.getRealityUrl() : "";
    }

    /**
     * 上传文件
     *
     * @param filename 文件名称
     * @param path     文件路径
     * @param bytes    文件流
     * @return
     */
    public String uploadFile(String filename, String path, byte[] bytes) {
        UploadFileRequest req = UploadFileRequest.newBuilder()
                .setFilename(filename)
                .setVpath(path)
                .setDatas(ByteString.copyFrom(bytes))
                .build();
        UploadFileResponse res = fileServiceBlockingStub.uploadFile(req);

        return res.getCode() == 0 ? res.getFileUrl() : "";
    }

    /**
     * 上传文件（指定 bucket）
     *
     * @param filename 文件名称
     * @param path     文件路径
     * @param bucket   bucket
     * @param bytes    文件流
     * @return
     */
    public String uploadFile(String filename, String path, String bucket, byte[] bytes) {
        UploadFileRequest req = UploadFileRequest.newBuilder()
                .setFilename(filename)
                .setVpath(path)
                .setBucket(bucket)
                .setDatas(ByteString.copyFrom(bytes))
                .build();
        UploadFileResponse res = fileServiceBlockingStub.uploadFile(req);
        return res.getCode() == 0 ? res.getFileUrl() : "";
    }

    /**
     * 读取文件
     *
     * @param key
     * @return
     */
    public byte[] readFile(String key) {
        ReadFileRequest req = ReadFileRequest.newBuilder().setFileUrl(key).build();
        ReadFileResponse res = fileServiceBlockingStub.readFile(req);

        if (res.getCode() == 0) {
            return res.getDatas().toByteArray();
        }

        return null;
    }

    /**
     * 从微信服务器下载图片至阿里云
     *
     * @param mediaIds
     * @return
     */
    public List<String> downloadImageFromWx(String[] mediaIds, int terminal) {
        String accessToken = "";
        List<String> lst = new LinkedList<>();

        GetAccessTokenRequest req = GetAccessTokenRequest.newBuilder().setType(terminal).build();
        GetAccessTokenResponse res = weChatServiceBlockingStub.getAccessToken(req);

        if (res.getCode() == 0 && !StringHelper.isNullOrWhiteSpace(res.getToken())) {
            accessToken = res.getToken();
        } else {
            logger.error("downloadImageFromWx(): {}", "accessToken不存在");
            return null;
        }

        for (String mediaId : mediaIds) {
            if (StringHelper.isNullOrWhiteSpace(mediaId)) {
                continue;
            }
            String requestUrl = String.format(Constant.WX_FILE_URL, accessToken, mediaId);

            try {
                URL url = new URL(requestUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDoInput(true);
                conn.setRequestMethod("GET");

                String ext = getFileExpandedName(conn.getHeaderField("Content-Type"));
                BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());

                byte[] bytes = convertInputStreamToBytes(bis);

                if (bytes != null) {
                    UploadImageRequest uploadImageRequest = UploadImageRequest.newBuilder()
                            .setFilename(String.format("%s.%s", Checksum.crc32(bytes), ext))
                            .setDatas(ByteString.copyFrom(bytes))
                            .setVpath("up/im/image")
                            .build();
                    UploadImageResponse uploadImageResponse = fileServiceBlockingStub.uploadImage(uploadImageRequest);

                    if (uploadImageResponse.getCode() == 0) {
                        lst.add(uploadImageResponse.getRealityUrl());
                    }
                }

                bis.close();
                conn.disconnect();
            } catch (Exception e) {
                logger.error("downloadImageFromWx(): {}", e.getMessage(), e);
            }
        }

        return lst;
    }

    /**
     * 根据内容类型获取扩展名
     *
     * @param contentType
     * @return
     */
    private static String getFileExpandedName(String contentType) {
        switch (contentType) {
            case "image/jpeg":
                return "jpg";
            case "audio/mpeg":
                return "mp3";
            case "audio/amr":
                return "amr";
            case "video/mp4":
            case "video/mpeg4":
                return "mp4";
            default:
                return "";
        }
    }

    private byte[] convertInputStreamToBytes(InputStream is) {
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            int ch;
            while ((ch = is.read()) != -1) {
                stream.write(ch);
            }
            byte bytes[] = stream.toByteArray();
            stream.close();

            return bytes;
        } catch (Exception e) {
            logger.error("convertInputStreamToBytes(): {}", e.getMessage(), e);
            return null;
        }
    }
}
