//
//  TravelAlbumOTGUploader.swift
//  suixinkan
//

import Foundation

/// 旅拍相册 OTG 上传服务协议。
@MainActor
protocol TravelAlbumOTGUploading {
    /// 上传本地照片并登记为旅拍相册素材。
    func upload(
        record: TravelAlbumOTGPhotoRecord,
        scenicId: Int,
        progress: @escaping (Int) -> Void
    ) async throws -> TravelAlbumMaterial
}

/// 旅拍相册 OTG 上传服务，负责 OSS 上传与 `upload-material` 素材登记。
@MainActor
final class TravelAlbumOTGUploader: TravelAlbumOTGUploading {
    private let uploader: OSSUploadService
    private let api: any TravelAlbumServing

    /// 初始化旅拍相册 OTG 上传服务。
    init(
        uploader: OSSUploadService? = nil,
        api: (any TravelAlbumServing)? = nil
    ) {
        self.uploader = uploader ?? NetworkServices.shared.ossUploadService
        self.api = api ?? NetworkServices.shared.travelAlbumAPI
    }

    /// 上传本地照片并登记为旅拍相册素材。
    func upload(
        record: TravelAlbumOTGPhotoRecord,
        scenicId: Int,
        progress: @escaping (Int) -> Void
    ) async throws -> TravelAlbumMaterial {
        guard record.albumId > 0 else {
            throw TravelAlbumOTGUploadError.invalidAlbum
        }
        guard !record.localPath.isEmpty,
              FileManager.default.fileExists(atPath: record.localPath) else {
            throw TravelAlbumOTGUploadError.localFileMissing
        }
        guard let clientPhotoId = TravelAlbumClientPhotoID.normalize(record.clientPhotoId) else {
            throw TravelAlbumOTGUploadError.clientPhotoIdMissing
        }

        let data = try Data(contentsOf: URL(fileURLWithPath: record.localPath))
        let remoteURL = try await uploader.uploadTravelAlbumMaterial(
            data: data,
            fileName: record.fileName,
            scenicId: scenicId,
            onProgress: progress
        )
        return try await api.uploadMaterial(
            TravelAlbumUploadMaterialRequest(
                userEquityTravelId: record.albumId,
                fileName: record.fileName,
                fileUrl: remoteURL,
                clientPhotoId: clientPhotoId
            )
        )
    }
}

/// 旅拍相册 OTG 上传错误。
enum TravelAlbumOTGUploadError: LocalizedError, Equatable {
    case invalidAlbum
    case localFileMissing
    case clientPhotoIdMissing

    var errorDescription: String? {
        switch self {
        case .invalidAlbum:
            return "请先选择有效的相册"
        case .localFileMissing:
            return "本地文件不存在，无法上传"
        case .clientPhotoIdMissing:
            return "照片标识缺失，请重新导入后重试"
        }
    }
}
