//
//  CloudTransferWorkers.swift
//  suixinkan
//

import Foundation
import Photos

/// 云盘 OSS 上传协议，便于传输管理注入测试替身。
@MainActor
protocol CloudDriveUploading {
    /// 上传云盘文件并返回远程 URL。
    func uploadCloudDriveFile(
        data: Data,
        fileName: String,
        fileType: Int,
        scenicId: Int,
        onProgress: @escaping (Int) -> Void
    ) async throws -> String
}

extension OSSUploadService: CloudDriveUploading {}

/// 云盘下载协议。
protocol CloudFileDownloading {
    /// 下载远程文件并返回本地临时文件 URL。
    func downloadFile(
        remoteURL: String,
        fileName: String,
        onProgress: @escaping @Sendable (Int) -> Void
    ) async throws -> URL
}

/// URLSession 实现的云盘下载器。
struct CloudURLSessionDownloader: CloudFileDownloading {
    func downloadFile(
        remoteURL: String,
        fileName: String,
        onProgress: @escaping @Sendable (Int) -> Void
    ) async throws -> URL {
        guard let url = URL(string: remoteURL) else {
            throw CloudTransferError.invalidURL
        }
        onProgress(1)
        let (temporaryURL, _) = try await URLSession.shared.download(from: url)
        try Task.checkCancellation()
        let directory = FileManager.default.temporaryDirectory.appendingPathComponent("cloud_drive_downloads", isDirectory: true)
        try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
        let destinationURL = directory.appendingPathComponent(CloudTransferFileName.sanitized(fileName))
        if FileManager.default.fileExists(atPath: destinationURL.path) {
            try FileManager.default.removeItem(at: destinationURL)
        }
        try FileManager.default.moveItem(at: temporaryURL, to: destinationURL)
        onProgress(100)
        return destinationURL
    }
}

/// 云盘下载后的系统相册保存协议。
protocol CloudPhotoSaving {
    /// 将图片或视频保存到系统相册。
    func saveToPhotoLibrary(fileURL: URL, fileType: Int) async throws
}

/// Photos 框架实现的相册保存器。
struct CloudPhotoLibrarySaver: CloudPhotoSaving {
    func saveToPhotoLibrary(fileURL: URL, fileType: Int) async throws {
        let status = await PHPhotoLibrary.requestAuthorization(for: .addOnly)
        guard status == .authorized || status == .limited else {
            throw CloudTransferError.photoPermissionDenied
        }

        try await PHPhotoLibrary.shared().performChanges {
            if fileType == 1 {
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fileURL)
            } else {
                PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: fileURL)
            }
        }
    }
}

/// 云盘传输错误。
enum CloudTransferError: LocalizedError, Equatable {
    case invalidURL
    case localFileMissing
    case photoPermissionDenied

    var errorDescription: String? {
        switch self {
        case .invalidURL:
            "文件地址不存在"
        case .localFileMissing:
            "本地文件不存在"
        case .photoPermissionDenied:
            "请允许访问相册后再下载"
        }
    }
}

/// 云盘传输文件名工具。
enum CloudTransferFileName {
    /// 清理文件名中不适合落盘的字符。
    static func sanitized(_ fileName: String) -> String {
        let trimmed = fileName.trimmingCharacters(in: .whitespacesAndNewlines)
        var unsafe = CharacterSet.controlCharacters
        unsafe.formUnion(CharacterSet(charactersIn: "/\\"))
        let value = trimmed.unicodeScalars.reduce(into: "") { result, scalar in
            result += unsafe.contains(scalar) ? "_" : String(scalar)
        }
        return value.isEmpty ? "cloud_file" : value
    }
}
