import Foundation
import UIKit

@MainActor
class FileUploadService {
    static let shared = FileUploadService()
    private let client = APIClient.shared

    /// 上传图片到 COS 并返回文件 ID + objectKey
    func uploadImageWithKey(_ image: UIImage, filename: String = "cover.jpg") async throws -> (fileId: String, objectKey: String) {
        guard let imageData = image.jpegData(compressionQuality: 0.75) else {
            throw FileUploadError.compressFailed
        }
        return try await uploadDataWithKey(imageData, filename: filename, mimeType: "image/jpeg")
    }

    /// 上传图片到 COS 并返回文件 ID
    func uploadImage(_ image: UIImage, filename: String = "avatar.jpg") async throws -> String {
        let result = try await uploadImageWithKey(image, filename: filename)
        return result.fileId
    }

    /// 上传原始数据到 COS 并返回 fileId + objectKey
    func uploadDataWithKey(_ data: Data, filename: String, mimeType: String) async throws -> (fileId: String, objectKey: String) {
        let urlReq = FileUploadUrlRequest(
            filename: filename, mimeType: mimeType, sizeBytes: data.count
        )
        let urlResp: FileUploadUrlResponse = try await client.request(
            "/files/upload-url", method: "POST", body: urlReq
        )

        var request = URLRequest(url: URL(string: urlResp.uploadUrl)!)
        request.httpMethod = "PUT"
        request.setValue(mimeType, forHTTPHeaderField: "Content-Type")
        request.httpBody = data
        let (_, response) = try await URLSession.shared.data(for: request)
        guard let httpResp = response as? HTTPURLResponse, httpResp.statusCode == 200 else {
            throw FileUploadError.uploadFailed
        }

        let confirmResp: FileConfirmUploadResponse = try await client.request(
            "/files/complete", method: "POST",
            body: FileConfirmUploadRequest(objectKey: urlResp.objectKey, checksum: nil)
        )

        return (fileId: confirmResp.id, objectKey: urlResp.objectKey)
    }

    /// 上传原始数据到 COS 并返回文件 ID
    func uploadData(_ data: Data, filename: String, mimeType: String) async throws -> String {
        let urlReq = FileUploadUrlRequest(
            filename: filename,
            mimeType: mimeType,
            sizeBytes: data.count
        )
        let urlResp: FileUploadUrlResponse = try await client.request(
            "/files/upload-url", method: "POST", body: urlReq
        )

        var request = URLRequest(url: URL(string: urlResp.uploadUrl)!)
        request.httpMethod = "PUT"
        request.setValue(mimeType, forHTTPHeaderField: "Content-Type")
        request.httpBody = data
        let (_, response) = try await URLSession.shared.data(for: request)
        guard let httpResp = response as? HTTPURLResponse, httpResp.statusCode == 200 else {
            throw FileUploadError.uploadFailed
        }

        let confirmResp: FileConfirmUploadResponse = try await client.request(
            "/files/complete", method: "POST",
            body: FileConfirmUploadRequest(objectKey: urlResp.objectKey, checksum: nil)
        )

        return confirmResp.id
    }

    /// 删除文件（COS + 数据库）
    func deleteFile(fileId: String) async throws {
        let _: GenericSuccessResponse = try await client.request("/files/\(fileId)", method: "DELETE")
    }

    /// 获取文件下载 URL
    func getDownloadUrl(fileId: String) async throws -> String {
        let detail: FileDetailResponse = try await client.request("/files/\(fileId)")
        return detail.downloadUrl
    }
}

enum FileUploadError: LocalizedError {
    case compressFailed
    case uploadFailed

    var errorDescription: String? {
        switch self {
        case .compressFailed: return "图片压缩失败"
        case .uploadFailed: return "上传失败，请重试"
        }
    }
}
