package com.fs.course.service.impl;

import com.fs.course.domain.FsUserCourseVideo;
import com.fs.course.mapper.FsUserCourseVideoMapper;
import com.fs.course.service.IFsUserCourseVideoService;
import com.fs.course.service.IFsUserVideoService;
import com.huaweicloud.sdk.cdn.v2.CdnClient;
import com.huaweicloud.sdk.cdn.v2.model.ShowDomainLocationStatsRequest;
import com.huaweicloud.sdk.cdn.v2.model.ShowDomainLocationStatsResponse;
import com.huaweicloud.sdk.cdn.v2.model.ShowDomainStatsRequest;
import com.huaweicloud.sdk.cdn.v2.model.ShowDomainStatsResponse;
import com.huaweicloud.sdk.cdn.v2.model.ShowTopUrlRequest;
import com.huaweicloud.sdk.cdn.v2.model.ShowTopUrlResponse;
import com.fs.common.core.domain.R;
import com.fs.course.service.IHuaweiObsService;
import com.huaweicloud.sdk.cdn.v2.region.CdnRegion;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.PutObjectRequest;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


@Service
public class HuaweiObsServiceImpl implements IHuaweiObsService {
    // 区域
    public static final String REGION_NORTH4 = "cn-north-4";
    public static final String REGION_NORTH1 = "cn-north-1";
    public static final String REGION_EAST2 = "cn-east-2";

    // ak/sk
    private static final String AK = "K2UTJGIN7UTZJR2XMXYG";
    private static final String SK = "sbyeNJLbcYmH6copxeFP9pAoksM4NIT9Zw4x0SRX";


    private static final String FIXED_VIDEO_PATH = "C:\\fs\\mergeVideo\\first.mp4";

    @Override
    public String uploadAndMergeVideo(File uploadedFile) throws IOException, InterruptedException {
        // 临时文件路径
        String mergedVideoPath = System.getProperty("java.io.tmpdir") + "merged_" + uploadedFile.getName();

        // 合并视频
        mergeVideos(FIXED_VIDEO_PATH, uploadedFile.getPath(), mergedVideoPath);

        // 上传到华为云VOD
//        String assetId = uploadPartFile(new File(mergedVideoPath));

        return "";
    }

    private void mergeVideos(String fixedVideoPath, String uploadedVideoPath, String outputPath) throws IOException, InterruptedException {

        String command = String.format("ffmpeg -i %s -i %s -filter_complex \"[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]\" -map \"[outv]\" -map \"[outa]\" %s", fixedVideoPath,uploadedVideoPath, outputPath);

        // 打印调试信息
        System.out.println("Executing command: " + command);

        // 执行命令
        Process process = Runtime.getRuntime().exec(command);

        // 等待命令执行完成
        int exitCode = process.waitFor();

        if (exitCode != 0) {
            // 读取并打印错误输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line;
            StringBuilder errorMsg = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                errorMsg.append(line).append(System.lineSeparator());
            }
            throw new IOException("FFmpeg 执行失败编码 " + exitCode + ":\n" + errorMsg);
        }

    }



    public static Map<String, Double> uploadProgress = new ConcurrentHashMap<>();
    public static Map<String, String> fileUrlMap = new ConcurrentHashMap<>();

    // 更新上传进度的方法
    public void updateProgress(String fileKey, double progress) {
        uploadProgress.put(fileKey, progress);
    }

    // 存储视频URL的方法
    public void storeFileUrl(String fileKey, String url) {
        fileUrlMap.put(fileKey, url);
    }
    /**
     * 分段上传
     * @param file 上传文件的本地路径
     */
    @Override
    public void uploadPartFile(File file,String fileKey) {
        String endPoint = "https://obs.cn-north-4.myhuaweicloud.com";

        // 创建ObsClient实例
        // 使用永久AK/SK初始化客户端
        ObsClient obsClient = new ObsClient(AK, SK,endPoint);
        // 使用临时AK/SK和SecurityToken初始化客户端
        // ObsClient obsClient = new ObsClient(ak, sk, securityToken, endPoint);
        String objKey = generateUploadFileName(file.getName());
        try {
            // 文件上传
            PutObjectRequest request = new PutObjectRequest("ylrz-obs2024", objKey);
            request.setFile(file);
            request.setProgressListener(status -> {
                double progress = status.getTransferPercentage();
                // 更新进度到UploadController
                updateProgress(fileKey, progress);
            });
            // 每上传1MB数据反馈上传进度
            request.setProgressInterval(1024 * 1024L);
            obsClient.putObject(request);
            String videoUrl = "https://obs.jy.cc/" + objKey;
            // 上传完成后存储URL
            storeFileUrl(fileKey, videoUrl);
            System.out.println("上传成功: " + videoUrl);
        } catch (ObsException e) {
            System.out.println("上传 失败");
            // 请求失败,打印http状态码
            System.out.println("HTTP Code:" + e.getResponseCode());
            // 请求失败,打印服务端错误码
            System.out.println("Error Code:" + e.getErrorCode());
            // 请求失败,打印详细错误信息
            System.out.println("Error Message:" + e.getErrorMessage());
            // 请求失败,打印请求id
            System.out.println("Request ID:" + e.getErrorRequestId());
            System.out.println("Host ID:" + e.getErrorHostId());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("上传失败");
            // 其他异常信息打印
            e.printStackTrace();
        }
    }


    public static String generateUploadFileName(String fileName) {
        // 获取文件扩展名
        String fileExtension = "";
        int i = fileName.lastIndexOf('.');
        if (i > 0) {
            fileExtension = fileName.substring(i + 1);
        }

        // 获取当前时间戳
        long currentTimeMillis = System.currentTimeMillis();

        // 生成上传文件名
        String uploadFileName = currentTimeMillis + "." + fileExtension;

        // 获取当前日期
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        String uploadDay = dateFormat.format(date);

        // 生成上传路径
        String key = "fs/" + uploadDay + "/" + uploadFileName;

        return key;
    }

    @Autowired
    private FsUserCourseVideoMapper courseVideoMapper;

    @Override
    public void uploadByCOS() throws IOException {

        List<FsUserCourseVideo> videos  = courseVideoMapper.selectVideoIsPrivate();
        for (FsUserCourseVideo video : videos) {
            String endPoint = "https://obs.cn-north-4.myhuaweicloud.com";

            ObsClient obsClient = new ObsClient(AK, SK, endPoint);
            String objKey = extractPathByRegex(video.getLineOne());
            String url = "https://obs.ylrztop.com/" + objKey;
            try {
                // 文件上传
                PutObjectRequest request = new PutObjectRequest("ylrz-obs2024", objKey, new ByteArrayInputStream(getObjectInputStream(objKey)));
                obsClient.putObject(request);

            } catch (ObsException e) {
                throw new ObsException("文件上传失败，" + e.getErrorMessage());
            } catch (Exception e) {
                System.out.println("上传失败");
                // 其他异常信息打印
            }
            System.out.println("obs地址："+url);
            FsUserCourseVideo video1 = new FsUserCourseVideo();
            video1.setVideoId(video.getVideoId());
            video1.setLineTwo(url);
            video1.setFileKey(objKey);
            courseVideoMapper.updateFsUserCourseVideo(video1);
        }

    }

    public static String extractPathByRegex(String urlString) {
        // ^https?://   匹配 http:// 或 https:// 开头
        // [^/]+        匹配域名部分（直到遇到第一个 '/'）
        // /            紧跟一个 '/'
        // 最后将这段内容替换为空字符串
        return urlString.replaceAll("^https?://[^/]+/", "");
    }

    private static final String YL_SECRET_ID = "AKIDiMq9lDf2EOM9lIfqqfKo7FNgM5meD0sT";
    private static final String YL_SECRET_KEY = "u5SuS80342xzx8FRBukza9lVNHKNMSaB";
    private static final String YL_BUCKET = "hylj-1323137866";
    private static final String YL_APP_ID = "1323137866";
    private static final String YL_REGION = "ap-chongqing";
    private static final String YL_PROXY = "hylj";

    private static COSClient cosClient = createClient();

    private static COSClient createClient() {
        // 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(YL_SECRET_ID,YL_SECRET_KEY);
        // 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(new Region(YL_REGION));
        // 生成cos客户端
        COSClient cosclient = new COSClient(cred, clientConfig);

        return cosclient;
    }

    private static byte[] getObjectInputStream(String key) throws IOException {
//        String key = "course/202517/1736224647237.mp4";
        GetObjectRequest getObjectRequest = new GetObjectRequest(YL_BUCKET, key);
        InputStream cosObjectInput = null;

        try {
            COSObject cosObject = cosClient.getObject(getObjectRequest);
            cosObjectInput = cosObject.getObjectContent();
        } catch (CosServiceException e) {
            e.printStackTrace();
        } catch (CosClientException e) {
            e.printStackTrace();
        }

        // 处理下载到的流
        // 这里是直接读取，按实际情况来处理
        byte[] bytes = null;
        try {
            bytes = IOUtils.toByteArray(cosObjectInput);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 用完流之后一定要调用 close()
            cosObjectInput.close();
        }
        return bytes;
    }
}
