package org.qinan.safetyeval.app.executor;

import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.qinan.safetyeval.client.api.FileStorageApi;
import org.qinan.safetyeval.client.co.FileInfoCO;
import org.qinan.safetyeval.client.dto.SingleResponse;
import org.qinan.safetyeval.domain.entity.FileStorage;
import org.qinan.safetyeval.domain.exception.BizException;
import org.qinan.safetyeval.domain.exception.ErrorCode;
import org.qinan.safetyeval.domain.service.FileStorageDomainService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文件存储管理执行器（App层）
 * <p>
 * 负责 filestorage 表的查询、删除、获取签名URL等管理操作。
 * 文件新增由 {@link FileUploadExecutor} 在上传时同步完成，本执行器不提供上传能力。
 * </p>
 *
 * @author safety-eval
 */
@Service
public class FileStorageExecutor implements FileStorageApi {

    private static final Logger log = LoggerFactory.getLogger(FileStorageExecutor.class);

    @Resource
    private FileStorageService fileStorageService;

    @Resource
    private FileStorageDomainService fileStorageDomainService;

    @Override
    public SingleResponse<FileInfoCO> getPresignedUrl(Integer fileId) {
        try {
            FileStorage fileStorage = fileStorageDomainService.getResource(fileId);
            FileInfo ossFileInfo = FileStorageHelper.buildOssFileInfo(fileStorage);
            FileStorageHelper.checkOssExists(fileStorageService, ossFileInfo);

            String presignedUrl = FileStorageHelper.generatePresignedUrl(fileStorageService, ossFileInfo);
            return SingleResponse.success(FileStorageHelper.toCO(fileStorage, presignedUrl));
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            log.error("Generate presigned URL failed: fileId={}", fileId, e);
            throw new BizException(ErrorCode.FILE_URL_GENERATE_FAILED, e);
        }
    }

    @Override
    public SingleResponse<FileInfoCO> getInfo(Integer fileId) {
        FileStorage fileStorage = fileStorageDomainService.getResource(fileId);
        String presignedUrl = null;
        try {
            FileInfo ossFileInfo = FileStorageHelper.buildOssFileInfo(fileStorage);
            if (fileStorageService.exists(ossFileInfo)) {
                presignedUrl = FileStorageHelper.generatePresignedUrl(fileStorageService, ossFileInfo);
            }
        } catch (Exception e) {
            log.warn("Failed to generate presigned URL for info query: fileId={}", fileId, e);
        }
        return SingleResponse.success(FileStorageHelper.toCO(fileStorage, presignedUrl));
    }

    @Override
    public SingleResponse<Void> delete(Integer fileId) {
        try {
            FileStorage fileStorage = fileStorageDomainService.getResource(fileId);

            FileInfo ossFileInfo = FileStorageHelper.buildOssFileInfo(fileStorage);
            if (!fileStorageService.delete(ossFileInfo)) {
                log.warn("OSS delete returned false for fileId={}, url={}", fileId, fileStorage.getUrl());
            }

            fileStorageDomainService.deleteResource(fileId);
            log.info("File deleted successfully: fileId={}, filename={}", fileId, fileStorage.getFilename());
            return SingleResponse.success();
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            log.error("File delete failed: fileId={}", fileId, e);
            throw new BizException(ErrorCode.FILE_DELETE_FAILED, e);
        }
    }

    @Override
    public SingleResponse<Void> deleteBatch(List<Integer> fileIds) {
        if (fileIds == null || fileIds.isEmpty()) {
            return SingleResponse.success();
        }
        for (Integer fileId : fileIds) {
            try {
                delete(fileId);
            } catch (Exception e) {
                log.warn("Batch delete: failed for fileId={}, continue with next", fileId, e);
            }
        }
        return SingleResponse.success();
    }

    @Override
    public SingleResponse<List<FileInfoCO>> listAll() {
        List<FileStorage> fileStorages = fileStorageDomainService.listAllResources();
        List<FileInfoCO> result = fileStorages.stream()
                .map(r -> FileStorageHelper.toCO(r, null))
                .collect(Collectors.toList());
        return SingleResponse.success(result);
    }

    @Override
    public SingleResponse<List<FileInfoCO>> listByCreator(String creatorUid) {
        List<FileStorage> fileStorages = fileStorageDomainService.listResourcesByCreator(creatorUid);
        List<FileInfoCO> result = fileStorages.stream()
                .map(r -> FileStorageHelper.toCO(r, null))
                .collect(Collectors.toList());
        return SingleResponse.success(result);
    }
}
