package com.lesingle.edu.common.util;

import com.aliyun.imm20200930.Client;
import com.aliyun.imm20200930.models.*;
import com.lesingle.edu.common.config.ImmConfig;
import com.lesingle.edu.dto.response.ImmTokenVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.Instant;

/**
 * 阿里云 IMM（智能媒体服务）工具类
 * <p>
 * 封装 WebOffice Token 生成、刷新等操作
 * </p>
 *
 * @author reading-platform
 * @since 2026-03-16
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ImmUtil {

    private final ImmConfig immConfig;

    /**
     * 生成 WebOffice Token（只读权限）
     *
     * @param sourceURI OSS 文件路径（如：oss://bucket-name/path/to/file.pptx）
     * @param name      文件名
     * @return WebOffice Token 信息
     */
    public ImmTokenVo generateWebofficeTokenReadOnly(String sourceURI, String name) {
        return generateWebofficeToken(sourceURI, name, true);
    }

    /**
     * 生成 WebOffice Token（编辑权限）
     *
     * @param sourceURI OSS 文件路径（如：oss://bucket-name/path/to/file.pptx）
     * @param name      文件名
     * @return WebOffice Token 信息
     */
    public ImmTokenVo generateWebofficeToken(String sourceURI, String name) {
        return generateWebofficeToken(sourceURI, name, false);
    }

    /**
     * 生成 WebOffice Token
     *
     * @param sourceURI  OSS 文件路径（如：oss://bucket-name/path/to/file.pptx）
     * @param name       文件名
     * @param isReadOnly 是否只读
     * @return WebOffice Token 信息
     */
    private ImmTokenVo generateWebofficeToken(String sourceURI, String name, boolean isReadOnly) {
        try {
            log.info("生成 WebOffice Token: sourceURI={}, name={}, isReadOnly={}", sourceURI, name, isReadOnly);

            // 获取 IMM 客户端
            Client client = getImmClient();

            // 构建权限配置
            WebofficePermission permission = new WebofficePermission()
                    .setReadonly(isReadOnly)
                    .setCopy(!isReadOnly)
                    .setExport(!isReadOnly)
                    .setPrint(!isReadOnly)
                    .setHistory(!isReadOnly)
                    .setRename(!isReadOnly);

            // 构建请求
            GetWebofficeURLRequest request = new GetWebofficeURLRequest()
                    .setProjectName(immConfig.getProjectName())
                    .setSourceURI(sourceURI)
                    .setFilename(name)
                    .setPermission(permission);

            // 发送请求
            GetWebofficeURLResponse response = client.getWebofficeURL(request);

            // 解析响应
            GetWebofficeURLResponseBody body = response.getBody();

            // 计算过期时间
            Long expireTime = null;
            if (body.getAccessTokenExpiredTime() != null) {
                try {
                    expireTime = Instant.parse(body.getAccessTokenExpiredTime()).toEpochMilli();
                } catch (Exception e) {
                    log.warn("解析过期时间失败：{}", e.getMessage());
                }
            }

            // 构建响应 VO
            ImmTokenVo tokenVo = ImmTokenVo.builder()
                    .webofficeURL(body.getWebofficeURL())
                    .accessToken(body.getAccessToken())
                    .refreshToken(body.getRefreshToken())
                    .expireTime(expireTime)
                    .build();

            log.info("WebOffice Token 生成成功：webofficeURL={}", maskString(body.getWebofficeURL()));
            return tokenVo;

        } catch (Exception e) {
            log.error("生成 WebOffice Token 失败：{}", e.getMessage(), e);
            throw new RuntimeException("生成 WebOffice Token 失败：" + e.getMessage(), e);
        }
    }

    /**
     * 刷新 WebOffice Token
     *
     * @param accessToken  当前访问凭证
     * @param refreshToken 刷新凭证
     * @return 刷新后的 Token 信息
     */
    public ImmTokenVo refreshWebofficeToken(String accessToken, String refreshToken) {
        try {
            log.info("刷新 WebOffice Token: accessToken={}, refreshToken={}",
                    maskString(accessToken), maskString(refreshToken));

            // 获取 IMM 客户端
            Client client = getImmClient();

            // 构建请求
            RefreshWebofficeTokenRequest request = new RefreshWebofficeTokenRequest()
                    .setProjectName(immConfig.getProjectName())
                    .setAccessToken(accessToken)
                    .setRefreshToken(refreshToken);

            // 发送请求
            RefreshWebofficeTokenResponse response = client.refreshWebofficeToken(request);

            // 解析响应
            RefreshWebofficeTokenResponseBody body = response.getBody();

            // 计算过期时间
            Long expireTime = null;
            if (body.getAccessTokenExpiredTime() != null) {
                try {
                    expireTime = Instant.parse(body.getAccessTokenExpiredTime()).toEpochMilli();
                } catch (Exception e) {
                    log.warn("解析过期时间失败：{}", e.getMessage());
                }
            }

            // 构建响应 VO（刷新 Token 不返回 webofficeURL）
            ImmTokenVo tokenVo = ImmTokenVo.builder()
                    .accessToken(body.getAccessToken())
                    .refreshToken(body.getRefreshToken())
                    .expireTime(expireTime)
                    .build();

            log.info("WebOffice Token 刷新成功");
            return tokenVo;

        } catch (Exception e) {
            log.error("刷新 WebOffice Token 失败：{}", e.getMessage(), e);
            throw new RuntimeException("刷新 WebOffice Token 失败：" + e.getMessage(), e);
        }
    }

    /**
     * 获取 IMM 客户端
     *
     * @return IMM 客户端实例
     */
    private Client getImmClient() {
        try {
            // 配置访问参数
            com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                    .setAccessKeyId(immConfig.getAccessKeyId())
                    .setAccessKeySecret(immConfig.getAccessKeySecret())
                    .setRegionId(immConfig.getRegion())
                    .setEndpoint(immConfig.getEndpoint());

            // 创建客户端
            return new Client(config);
        } catch (Exception e) {
            log.error("创建 IMM 客户端失败：{}", e.getMessage(), e);
            throw new RuntimeException("创建 IMM 客户端失败：" + e.getMessage(), e);
        }
    }

    /**
     * 脱敏显示字符串（用于日志）
     *
     * @param str 原始字符串
     * @return 脱敏后的字符串
     */
    private String maskString(String str) {
        if (str == null || str.length() < 10) {
            return "***";
        }
        return str.substring(0, 3) + "..." + str.substring(str.length() - 3);
    }

    /**
     * 将 OSS URL 转换为 IMM 所需的 SourceURI 格式
     *
     * @param ossUrl OSS 文件 URL
     * @return IMM SourceURI 格式
     */
    public String convertOssUrlToSourceURI(String ossUrl) {
        if (ossUrl == null || ossUrl.isEmpty()) {
            throw new IllegalArgumentException("OSS URL 不能为空");
        }

        // 如果已经是 oss:// 格式，直接返回
        if (ossUrl.startsWith("oss://")) {
            return ossUrl;
        }

        // 从完整 URL 提取 bucket 和 object key
        // 格式：https://bucket-name.endpoint/object-key
        try {
            String url = ossUrl.replace("https://", "");
            int firstSlash = url.indexOf("/");
            if (firstSlash == -1) {
                throw new IllegalArgumentException("无效的 OSS URL 格式：" + ossUrl);
            }

            String bucketAndEndpoint = url.substring(0, firstSlash);
            String objectKey = url.substring(firstSlash + 1);

            // 提取 bucket 名称（endpoint 之前）
            String bucket = bucketAndEndpoint.split("\\.")[0];

            // 构建 oss://bucket/object-key 格式
            return "oss://" + bucket + "/" + objectKey;
        } catch (Exception e) {
            log.error("解析 OSS URL 失败：{}", e.getMessage(), e);
            throw new IllegalArgumentException("无效的 OSS URL 格式：" + ossUrl, e);
        }
    }
}
