package com.yd.oss.api.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.oss.api.service.ApiOssService;
import com.yd.oss.feign.request.ApiUploadFileRequest;
import com.yd.oss.feign.response.ApiBatchUploadResponse;
import com.yd.oss.feign.response.ApiFileMetadataResponse;
import com.yd.oss.feign.response.ApiUploadResponse;
import com.yd.oss.service.dto.FileMetadata;
import com.yd.oss.service.dto.OssUploadFileReqDto;
import com.yd.oss.service.dto.OssUploadFileResDto;
import com.yd.oss.service.dto.UploadResult;
import com.yd.oss.service.service.OssService;
import com.yd.oss.service.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ApiOssServiceImpl implements ApiOssService {

    @Autowired
    private OssService ossService;

    /**
     * 上传文件
     * @param file 上传的文件
     * @param bucket oss桶（不传值使用默认的oss的桶）
     * @param provider oss云提供商（不传值使用默认的oss云提供商）
     * @param uploadUser 上传人用户id
     * @return
     */
    @Override
    public Result<ApiUploadResponse> uploadFile(MultipartFile file, String bucket, String provider, String uploadUser,String projectBizId) {
        ApiUploadResponse response = new ApiUploadResponse();
        try {

            // 上传文件
            OssUploadFileResDto ossUploadFileDto = ossService.uploadFile(file.getInputStream(), file.getOriginalFilename(),
                    bucket, uploadUser, FileUtil.getFileType(file.getOriginalFilename()),projectBizId);

            // 获取上传结果（包含文件信息和访问URL）
            UploadResult result = ossService.getUploadResult(ossUploadFileDto.getFileKey(), Duration.ofHours(1));

            BeanUtils.copyProperties(result,response);
            response.setFileBizId(ossUploadFileDto.getFileBizId());
            response.setUrl(ossUploadFileDto.getUrl());
            return Result.success(response);
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return Result.fail("文件上传失败");
        }
    }

    /**
     * 上传文件 - body入参方式（新，推荐）
     * @param file
     * @param request
     * @return
     */
    @Override
    public Result<ApiUploadResponse> uploadFileBody(MultipartFile file, ApiUploadFileRequest request) {
        ApiUploadResponse response = null;
        OssUploadFileReqDto reqDto = new OssUploadFileReqDto();
        BeanUtils.copyProperties(request,reqDto);
        OssUploadFileResDto fileResDto = ossService.uploadFileBody(file,reqDto);
        if (!Objects.isNull(fileResDto)) {
            response = new ApiUploadResponse();
            BeanUtils.copyProperties(fileResDto,response);
        }
        return Result.success(response);
    }

    /**
     * 下载文件
     * @param fileKey 文件唯一标识
     * @param bucket oss桶（不传值使用默认的oss的桶）
     * @param provider oss云提供商（不传值使用默认的oss云提供商）
     * @param response
     */
    @Override
    public void downloadFile(String fileKey, String bucket, String provider, HttpServletResponse response) {
        try {
            // 如果指定了提供商，则切换
            if (StringUtils.isNotBlank(provider)) {
                ossService.switchProvider(provider);
            }

            // 下载文件
            InputStream inputStream = ossService.downloadFile(fileKey, bucket);

            // 设置响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileKey + "\"");

            // 将文件流写入响应
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
        } catch (IOException e) {
            log.error("文件下载失败: {}", fileKey, e);
            throw new RuntimeException("文件下载失败: " + fileKey, e);
        }
    }

    /**
     * 删除文件
     * @param fileKey 文件唯一标识
     * @param bucket oss桶（不传值使用默认的oss的桶）
     * @param provider oss云提供商（不传值使用默认的oss云提供商）
     * @param operator 操作用户
     * @return
     */
    @Override
    public Result<Boolean> deleteFile(String fileKey, String bucket, String provider, String operator) {
        try {
            // 如果指定了提供商，则切换
            if (StringUtils.isNotBlank(provider)) {
                ossService.switchProvider(provider);
            }

            // 删除文件
            boolean result = ossService.deleteFile(fileKey, bucket, operator);

            return Result.success(result);
        } catch (Exception e) {
            log.error("文件删除失败: {}", fileKey, e);
            return Result.fail("文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件URL
     * @param fileKey 文件唯一标识
     * @param bucket oss桶（不传值使用默认的oss的桶）
     * @param provider oss云提供商（不传值使用默认的oss云提供商）
     * @param expirySeconds url的过期秒数
     * @return
     */
    @Override
    public Result<String> getFileUrl(String fileKey, String bucket, String provider, Long expirySeconds) {
        try {
            // 如果指定了提供商，则切换
            if (StringUtils.isNotBlank(provider)) {
                ossService.switchProvider(provider);
            }

            // 获取文件URL
            String url = ossService.getFileUrl(fileKey, bucket, Duration.ofSeconds(expirySeconds));

            return Result.success(url);
        } catch (Exception e) {
            log.error("获取文件URL失败: {}", fileKey, e);
            return Result.fail("获取文件URL失败: " + e.getMessage());
        }
    }

    /**
     * 切换OSS提供商
     * @param providerName OSS提供商名称
     * @return
     */
    @Override
    public Result<Boolean> switchProvider(String providerName) {
        try {
            // 切换OSS提供商
            ossService.switchProvider(providerName);

            return Result.success(true);
        } catch (Exception e) {
            log.error("切换OSS提供商失败: {}", providerName, e);
            return Result.fail("切换OSS提供商失败: " + e.getMessage());
        }
    }

    /**
     * 检查文件是否存在
     * @param fileKey 文件唯一标识
     * @param bucket oss桶（不传值使用默认的oss的桶）
     * @param provider oss云提供商（不传值使用默认的oss云提供商）
     * @return
     */
    @Override
    public Result<Boolean> doesFileExist(String fileKey, String bucket, String provider) {
        try {
            // 如果指定了提供商，则切换
            if (StringUtils.isNotBlank(provider)) {
                ossService.switchProvider(provider);
            }

            // 检查文件是否存在
            boolean exists = ossService.doesFileExist(fileKey, bucket);

            return Result.success(exists);
        } catch (Exception e) {
            log.error("检查文件存在失败: {}", fileKey, e);
            return Result.fail("检查文件存在失败: " + e.getMessage());
        }
    }

    /**
     * 获取文件元数据
     * @param fileKey 文件唯一标识
     * @param bucket oss桶（不传值使用默认的oss的桶）
     * @param provider oss云提供商（不传值使用默认的oss云提供商）
     * @return
     */
    @Override
    public Result<ApiFileMetadataResponse> getFileMetadata(String fileKey, String bucket, String provider) {
        ApiFileMetadataResponse response = new ApiFileMetadataResponse();
        try {
            // 如果指定了提供商，则切换
            if (StringUtils.isNotBlank(provider)) {
                ossService.switchProvider(provider);
            }

            // 获取文件元数据
            FileMetadata metadata = ossService.getFileMetadata(fileKey, bucket);
            BeanUtils.copyProperties(metadata,response);
            return Result.success(response);
        } catch (Exception e) {
            log.error("获取文件元数据失败: {}", fileKey, e);
            return Result.fail("获取文件元数据失败: " + e.getMessage());
        }
    }

    /**
     * 批量上传文件
     * @param files 文件列表
     * @param request 批量上传请求参数
     * @return 批量上传响应
     */
    @Override
    public Result<ApiBatchUploadResponse> batchUploadFiles(List<MultipartFile> files, ApiUploadFileRequest request) {
        try {
            // 转换请求参数
            OssUploadFileReqDto reqDto = new OssUploadFileReqDto();
            BeanUtils.copyProperties(request, reqDto);

            // 调用服务层批量上传方法
            ApiBatchUploadResponse response = ossService.batchUploadFiles(files, reqDto);

            return Result.success(response);
        } catch (Exception e) {
            log.error("批量上传文件失败", e);
            return Result.fail("批量上传文件失败: " + e.getMessage());
        }
    }

}
