package com.example.demo.service;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID;

/**
 * 腾讯云COS对象存储服务
 */
@Service
public class CosService {

    private static final Logger logger = LoggerFactory.getLogger(CosService.class);

    @Autowired(required = false)
    private COSClient cosClient;

    @Autowired
    private com.example.demo.config.CosConfig cosConfig;

    @Autowired
    private UserErrorLogService userErrorLogService;

    /**
     * 检查COS是否已启用
     */
    public boolean isEnabled() {
        return cosConfig.isEnabled() && cosClient != null;
    }

    /**
     * 从URL下载视频并上传到COS
     *
     * @param videoUrl 视频URL
     * @param filename 文件名（可选，如果为null则自动生成）
     * @return COS中的文件URL，如果失败则返回null
     */
    public String uploadVideoFromUrl(String videoUrl, String filename) {
        if (!isEnabled()) {
            logger.warn("COS未启用，跳过上传");
            return null;
        }

        try {
            logger.info("开始从URL下载视频: {}", videoUrl);

            // 下载视频到内存（适用于小于100MB的视频）
            URL url = new URL(videoUrl);
            URLConnection conn = url.openConnection();
            conn.setConnectTimeout(30000); // 30秒连接超时
            conn.setReadTimeout(120000);   // 2分钟读取超时

            // 获取内容类型和长度
            String contentType = conn.getContentType();
            int contentLength = conn.getContentLength();

            logger.info("视频信息 - 类型: {}, 大小: {} bytes", contentType, contentLength);

            // 检查文件大小（最大200MB）
            if (contentLength > 200 * 1024 * 1024) {
                logger.error("视频文件过大: {} MB，超过200MB限制", contentLength / (1024 * 1024));
                return null;
            }

            // 读取视频内容
            byte[] videoBytes;
            try (InputStream inputStream = conn.getInputStream()) {
                videoBytes = inputStream.readAllBytes();
            }

            logger.info("视频下载完成，大小: {} KB", videoBytes.length / 1024);

            // 生成文件名
            if (filename == null || filename.isEmpty()) {
                String extension = getFileExtension(videoUrl, contentType);
                filename = generateFilename(extension);
            }

            // 上传到COS
            return uploadBytes(videoBytes, filename, contentType);

        } catch (Exception e) {
            logger.error("从URL上传视频到COS失败: {}", videoUrl, e);
            logFileError(filename, "从URL上传视频到COS失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 上传Base64图片到COS
     *
     * @param base64Data Base64编码的图片数据（可以带或不带data URI前缀）
     * @param filename 文件名（可选，如果为null则自动生成）
     * @return COS文件URL，如果失败则返回null
     */
    public String uploadBase64Image(String base64Data, String filename) {
        if (!isEnabled()) {
            logger.warn("COS未启用，跳过上传");
            return null;
        }

        try {
            // 解析Base64数据
            String actualBase64 = base64Data;
            String contentType = "image/png"; // 默认类型

            // 如果有data URI前缀，解析它
            if (base64Data.startsWith("data:")) {
                int commaIndex = base64Data.indexOf(',');
                if (commaIndex > 0) {
                    String header = base64Data.substring(0, commaIndex);
                    actualBase64 = base64Data.substring(commaIndex + 1);
                    // 解析内容类型
                    if (header.contains("image/jpeg") || header.contains("image/jpg")) {
                        contentType = "image/jpeg";
                    } else if (header.contains("image/png")) {
                        contentType = "image/png";
                    } else if (header.contains("image/gif")) {
                        contentType = "image/gif";
                    } else if (header.contains("image/webp")) {
                        contentType = "image/webp";
                    }
                }
            }

            // 解码Base64
            byte[] imageBytes = java.util.Base64.getDecoder().decode(actualBase64);
            logger.info("解码Base64图片成功，大小: {} KB", imageBytes.length / 1024);

            // 生成文件名
            if (filename == null || filename.isEmpty()) {
                String extension = contentType.equals("image/jpeg") ? ".jpg" : 
                                  contentType.equals("image/png") ? ".png" : 
                                  contentType.equals("image/gif") ? ".gif" : ".png";
                filename = generateFilename(extension);
            }

            // 上传到COS（使用images目录）
            return uploadImageBytes(imageBytes, filename, contentType);

        } catch (Exception e) {
            logger.error("上传Base64图片到COS失败", e);
            return null;
        }
    }

    /**
     * 上传图片字节数组到COS（存储在配置的目录下）
     */
    private String uploadImageBytes(byte[] bytes, String filename, String contentType) {
        try {
            // 添加前缀目录
            String key = buildObjectKey(filename);

            // 设置元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(bytes.length);
            metadata.setContentType(contentType);

            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                cosConfig.getBucketName(),
                key,
                new ByteArrayInputStream(bytes),
                metadata
            );

            // 执行上传
            logger.info("开始上传图片到COS: bucket={}, key={}", cosConfig.getBucketName(), key);
            PutObjectResult result = cosClient.putObject(putObjectRequest);
            logger.info("图片上传成功，ETag: {}", result.getETag());

            // 生成访问URL
            String fileUrl = getPublicUrl(key);
            logger.info("图片URL: {}", fileUrl);

            return fileUrl;

        } catch (Exception e) {
            logger.error("上传图片到COS失败: {}", filename, e);
            return null;
        }
    }

    /**
     * 上传字节数组到COS
     *
     * @param bytes 文件字节数组
     * @param filename 文件名
     * @param contentType 内容类型
     * @return COS文件URL
     */
    public String uploadBytes(byte[] bytes, String filename, String contentType) {
        if (!isEnabled()) {
            logger.warn("COS未启用，跳过上传");
            return null;
        }

        try {
            // 构建对象键（带日期目录结构）
            String key = buildObjectKey(filename);

            // 设置元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(bytes.length);
            if (contentType != null && !contentType.isEmpty()) {
                metadata.setContentType(contentType);
            } else {
                metadata.setContentType("video/mp4"); // 默认类型
            }

            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                cosConfig.getBucketName(),
                key,
                new ByteArrayInputStream(bytes),
                metadata
            );

            // 执行上传
            logger.info("开始上传到COS: bucket={}, key={}", cosConfig.getBucketName(), key);
            PutObjectResult result = cosClient.putObject(putObjectRequest);
            logger.info("上传成功，ETag: {}", result.getETag());

            // 生成访问URL
            String fileUrl = getPublicUrl(key);
            logger.info("文件URL: {}", fileUrl);

            return fileUrl;

        } catch (Exception e) {
            logger.error("上传文件到COS失败: {}", filename, e);
            return null;
        }
    }

    /**
     * 上传本地文件到COS
     *
     * @param file 本地文件
     * @param filename 目标文件名
     * @return COS文件URL
     */
    public String uploadFile(File file, String filename) {
        if (!isEnabled()) {
            logger.warn("COS未启用，跳过上传");
            return null;
        }

        try {
            String key = buildObjectKey(filename);

            PutObjectRequest putObjectRequest = new PutObjectRequest(
                cosConfig.getBucketName(),
                key,
                file
            );

            logger.info("开始上传文件到COS: {}", file.getAbsolutePath());
            PutObjectResult result = cosClient.putObject(putObjectRequest);
            logger.info("上传成功，ETag: {}", result.getETag());

            return getPublicUrl(key);

        } catch (Exception e) {
            logger.error("上传文件到COS失败: {}", file.getName(), e);
            return null;
        }
    }

    /**
     * 生成对象键（添加配置的前缀目录）
     */
    private String buildObjectKey(String filename) {
        String prefix = cosConfig.getPrefix();
        if (prefix != null && !prefix.isEmpty()) {
            // 确保前缀以 / 结尾
            if (!prefix.endsWith("/")) {
                prefix = prefix + "/";
            }
            return prefix + filename;
        }
        return filename;
    }

    /**
     * 生成唯一文件名
     */
    private String generateFilename(String extension) {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid + extension;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String url, String contentType) {
        // 优先从URL中提取扩展名
        if (url != null) {
            int lastDot = url.lastIndexOf('.');
            int lastSlash = url.lastIndexOf('/');
            int lastQuestion = url.lastIndexOf('?');

            if (lastDot > lastSlash && lastDot > 0) {
                String ext = url.substring(lastDot, lastQuestion > lastDot ? lastQuestion : url.length());
                if (ext.length() <= 5) { // 合理的扩展名长度
                    return ext;
                }
            }
        }

        // 从Content-Type推断扩展名
        if (contentType != null) {
            if (contentType.contains("mp4")) return ".mp4";
            if (contentType.contains("webm")) return ".webm";
            if (contentType.contains("avi")) return ".avi";
            if (contentType.contains("mov")) return ".mov";
        }

        // 默认扩展名
        return ".mp4";
    }

    /**
     * 生成公共访问URL
     */
    private String getPublicUrl(String key) {
        // COS公共读URL格式：https://{bucket-name}.cos.{region}.myqcloud.com/{key}
        return String.format("https://%s.cos.%s.myqcloud.com/%s",
            cosConfig.getBucketName(),
            cosConfig.getRegion(),
            key);
    }

    /**
     * 关闭COS客户端
     */
    public void shutdown() {
        if (cosClient != null) {
            cosClient.shutdown();
        }
    }

    /**
     * 记录文件上传错误
     */
    private void logFileError(String filename, String errorMessage) {
        try {
            userErrorLogService.logErrorAsync(
                null,
                com.example.demo.model.UserErrorLog.ErrorType.FILE_UPLOAD_ERROR,
                errorMessage,
                "CosService",
                null,
                filename
            );
        } catch (Exception e) {
            logger.warn("记录文件上传错误日志失败: {}", e.getMessage());
        }
    }
}
