package com.ruoyi.system.config;

import cn.hutool.core.util.IdUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.teaopenapi.models.Config;
import com.aliyuncs.exceptions.ClientException;
import com.ruoyi.common.constant.AliKeyConfig;
import com.ruoyi.common.core.domain.entity.ShopUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import static com.alibaba.fastjson2.JSONObject.toJSONString;

public class AliConfig {



    private static final Logger log = LoggerFactory.getLogger(AliConfig.class);
    public static Client createClient() {
        Config config = new Config()
                // 配置 AccessKey ID，请确保代码运行环境配置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
                .setAccessKeyId(AliKeyConfig.ACCESS_KEY_ID)
                // 配置 AccessKey Secret，请确保代码运行环境配置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
                .setAccessKeySecret(AliKeyConfig.ACCESS_KEY_SECRET);
        // System.getenv()方法表示获取系统环境变量，不要直接在getenv()中填入AccessKey信息。

        // 配置 Endpoint。中国站请使用dysmsapi.aliyuncs.com
        config.endpoint = "dysmsapi.aliyuncs.com";

        try {
            return new Client(config);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        ShopUser shopUser = new ShopUser();
        shopUser.setPhone("13943965645");
        shopUser.setCode("123456");
        sendMsg(shopUser);
    }

    public static String sendMsg(ShopUser shopUser) {
        // 初始化请求客户端
        Client client = AliConfig.createClient();

        // 1. 生成6位验证码
        String code = String.valueOf((int)((Math.random()*9+1)*100000));

        //String templateParam = "{\"name\":\"" + shopUser.getUsername() + "\",\"number\":\""+ shopUser.getPhone() +"\"}";

        String templateParam = "{'code':"+ code + "}";

        // 构造API请求对象，请替换请求参数值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(shopUser.getPhone())
                .setSignName("北京盛兴平商贸")
                .setTemplateCode("SMS_323405385")
                .setTemplateParam(templateParam); // TemplateParam为序列化后的JSON字符串。

        // 获取响应对象
        SendSmsResponse sendSmsResponse;
        try {
            sendSmsResponse = client.sendSms(sendSmsRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        log.info("aliyun 发送验证码返回信息：{}", toJSONString(sendSmsResponse));

        if (sendSmsResponse.getStatusCode() == 200){
            return code;
        }
        return null;
    }


    public static String ossUp(String objectName,String fileName, InputStream inputStream){
        // 配置参数
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        String accessKeyId = AliKeyConfig.ACCESS_KEY_ID;
        String accessKeySecret = AliKeyConfig.ACCESS_KEY_SECRET;
        String bucketName = "wenzhuangmusic";

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String path = objectName + IdUtil.fastUUID() + suffix;
        try {
            // 上传字符串内容作为文件
            ossClient.putObject(bucketName, path, inputStream);
            System.out.println("文件上传成功：" + objectName);
            return "/file/download/"+path;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭OSSClient
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }


    public static byte[] ossDown(String objectName) {
        // 配置参数
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        String accessKeyId = AliKeyConfig.ACCESS_KEY_ID;
        String accessKeySecret = AliKeyConfig.ACCESS_KEY_SECRET;
        String bucketName = "wenzhuangmusic";

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元数据以及一个输入流。
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            InputStream inputStream = ossObject.getObjectContent();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            // 读取文件内容到字节数组。
            byte[] readBuffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(readBuffer)) != -1) {
                byteArrayOutputStream.write(readBuffer, 0, bytesRead);
            }
            // 获取最终的字节数组。
            byte[] fileBytes = byteArrayOutputStream.toByteArray();
            // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
            inputStream.close();
            byteArrayOutputStream.close();
            // ossObject对象使用完毕后必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
            ossObject.close();
            return fileBytes;
        } catch (OSSException oe) {
            oe.printStackTrace();
        } catch (Throwable ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }

    /**
     * 流式下载OSS文件，直接写入输出流，避免一次性加载整个文件到内存
     * 
     * @param objectName OSS对象名称
     * @param outputStream 输出流
     * @return 是否下载成功
     */
    public static boolean ossDownloadStream(String objectName, java.io.OutputStream outputStream) {
        // 配置参数
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        String accessKeyId = AliKeyConfig.ACCESS_KEY_ID;
        String accessKeySecret = AliKeyConfig.ACCESS_KEY_SECRET;
        String bucketName = "wenzhuangmusic";

        OSS ossClient = null;
        InputStream inputStream = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            
            // 判断文件是否存在
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                log.error("OSS文件不存在: {}", objectName);
                return false;
            }
            
            // 获取文件对象
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            inputStream = ossObject.getObjectContent();
            
            // 使用缓冲区进行流式传输
            byte[] buffer = new byte[8192]; // 8KB缓冲区
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                try {
                    outputStream.write(buffer, 0, bytesRead);
                    // 定期刷新输出流，避免缓冲区溢出
                    if (bytesRead == buffer.length) {
                        outputStream.flush();
                    }
                } catch (java.io.IOException e) {
                    // 检查是否为客户端断开连接的错误
                    if (e.getMessage() != null && 
                        (e.getMessage().contains("Broken pipe") || 
                         e.getMessage().contains("Connection reset by peer") ||
                         e.getMessage().contains("连接被对方重置") ||
                         e.getMessage().contains("你的主机中的软件中止了一个已建立的连接") ||
                         e.getMessage().contains("Software caused connection abort") ||
                         e.getMessage().contains("SocketTimeoutException"))) {
                        // 客户端已断开连接，记录日志但不作为错误处理
                        log.info("客户端断开连接，文件传输中断: {}", e.getMessage());
                        return true; // 返回true，因为这不是服务器端的错误
                    } else {
                        // 其他IO错误，重新抛出
                        throw e;
                    }
                }
            }
            outputStream.flush();
            return true;
        } catch (java.io.IOException e) {
            // 检查是否为客户端断开连接的错误
            if (e.getMessage() != null && 
                (e.getMessage().contains("Broken pipe") || 
                 e.getMessage().contains("Connection reset by peer") ||
                 e.getMessage().contains("连接被对方重置") ||
                 e.getMessage().contains("你的主机中的软件中止了一个已建立的连接") ||
                 e.getMessage().contains("Software caused connection abort") ||
                 e.getMessage().contains("SocketTimeoutException"))) {
                // 客户端已断开连接，记录日志但不作为错误处理
                log.info("客户端断开连接，文件传输中断: {}", e.getMessage());
                return true; // 返回true，因为这不是服务器端的错误
            } else {
                // 其他IO错误
                log.error("下载OSS文件失败: {}", e.getMessage());
                return false;
            }
        } catch (Exception e) {
            log.error("下载OSS文件失败: {}", e.getMessage());
            return false;
        } finally {
            // 关闭资源
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (java.io.IOException e) {
                log.error("关闭输入流失败: {}", e.getMessage());
            }
            
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 获取OSS对象的长度
     * 
     * @param objectName OSS对象名称
     * @return 文件长度，如果获取失败返回null
     */
    public static Long getOssObjectLength(String objectName) {
        // 配置参数
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        String accessKeyId = AliKeyConfig.ACCESS_KEY_ID;
        String accessKeySecret = AliKeyConfig.ACCESS_KEY_SECRET;
        String bucketName = "wenzhuangmusic";

        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            
            // 判断文件是否存在
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                log.error("OSS文件不存在: {}", objectName);
                return null;
            }
            
            // 获取文件元数据
            com.aliyun.oss.model.ObjectMetadata metadata = ossClient.getObjectMetadata(bucketName, objectName);
            return metadata.getContentLength();
            
        } catch (Exception e) {
            log.error("获取OSS文件长度失败: {}", e.getMessage());
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 范围下载OSS文件，支持HTTP Range请求
     * 
     * @param objectName OSS对象名称
     * @param outputStream 输出流
     * @param start 开始字节位置
     * @param end 结束字节位置
     * @return 是否下载成功
     */
    public static boolean ossDownloadStreamRange(String objectName, java.io.OutputStream outputStream, long start, long end) {
        // 配置参数
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        String accessKeyId = AliKeyConfig.ACCESS_KEY_ID;
        String accessKeySecret = AliKeyConfig.ACCESS_KEY_SECRET;
        String bucketName = "wenzhuangmusic";

        OSS ossClient = null;
        InputStream inputStream = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            
            // 判断文件是否存在
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                log.error("OSS文件不存在: {}", objectName);
                return false;
            }
            
            // 创建范围请求
            com.aliyun.oss.model.GetObjectRequest getObjectRequest = new com.aliyun.oss.model.GetObjectRequest(bucketName, objectName);
            getObjectRequest.setRange(start, end);
            
            // 获取文件对象
            OSSObject ossObject = ossClient.getObject(getObjectRequest);
            inputStream = ossObject.getObjectContent();
            
            // 使用缓冲区进行流式传输
            byte[] buffer = new byte[8192]; // 8KB缓冲区
            int bytesRead;
            long totalBytesRead = 0;
            long expectedBytes = end - start + 1;
            
            while ((bytesRead = inputStream.read(buffer)) != -1 && totalBytesRead < expectedBytes) {
                try {
                    // 确保不超过请求的字节范围
                    int bytesToWrite = (int) Math.min(bytesRead, expectedBytes - totalBytesRead);
                    outputStream.write(buffer, 0, bytesToWrite);
                    totalBytesRead += bytesToWrite;
                    
                    // 定期刷新输出流
                    if (bytesToWrite == buffer.length) {
                        outputStream.flush();
                    }
                } catch (java.io.IOException e) {
                    // 检查是否为客户端断开连接的错误
                    if (e.getMessage() != null && 
                        (e.getMessage().contains("Broken pipe") || 
                         e.getMessage().contains("Connection reset by peer") ||
                         e.getMessage().contains("连接被对方重置") ||
                         e.getMessage().contains("你的主机中的软件中止了一个已建立的连接") ||
                         e.getMessage().contains("Software caused connection abort") ||
                         e.getMessage().contains("SocketTimeoutException"))) {
                        // 客户端已断开连接，记录日志但不作为错误处理
                        log.info("客户端断开连接，文件传输中断: {}", e.getMessage());
                        return true; // 返回true，因为这不是服务器端的错误
                    } else {
                        // 其他IO错误，重新抛出
                        throw e;
                    }
                }
            }
            outputStream.flush();
            return true;
            
        } catch (java.io.IOException e) {
            // 检查是否为客户端断开连接的错误
            if (e.getMessage() != null && 
                (e.getMessage().contains("Broken pipe") || 
                 e.getMessage().contains("Connection reset by peer") ||
                 e.getMessage().contains("连接被对方重置") ||
                 e.getMessage().contains("你的主机中的软件中止了一个已建立的连接") ||
                 e.getMessage().contains("Software caused connection abort") ||
                 e.getMessage().contains("SocketTimeoutException"))) {
                // 客户端已断开连接，记录日志但不作为错误处理
                log.info("客户端断开连接，文件传输中断: {}", e.getMessage());
                return true; // 返回true，因为这不是服务器端的错误
            } else {
                // 其他IO错误
                log.error("范围下载OSS文件失败: {}", e.getMessage());
                return false;
            }
        } catch (Exception e) {
            log.error("范围下载OSS文件失败: {}", e.getMessage());
            return false;
        } finally {
            // 关闭资源
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (java.io.IOException e) {
                log.error("关闭输入流失败: {}", e.getMessage());
            }
            
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

}
