// ── Blob Storage Client ─────────────────────────────────────
// Generic Azure Blob Storage client via platform-service SAS tokens.
// Upload files to Azure Blob using SAS URL from POST /api/blob/sas.
// Product apps configure with BLPlatformConfig.

import Foundation

/// Response from platform-service SAS token endpoint.
public struct BLSASResponse: Codable, Sendable {
    public let sasUrl: String
    public let blobUrl: String
    public let container: String
    public let blobName: String
}

/// Generic blob storage client for all ByteLyst iOS apps.
/// Handles SAS token acquisition + direct Azure Blob upload.
public final class BLBlobClient {

    private let config: BLPlatformConfig
    private let client: BLPlatformClient

    public init(config: BLPlatformConfig, client: BLPlatformClient) {
        self.config = config
        self.client = client
    }

    // MARK: - Upload

    /// Upload data to Azure Blob Storage.
    /// 1. Acquires SAS token from platform-service
    /// 2. Uploads directly to Azure Blob using the SAS URL
    /// Returns the permanent blob URL on success.
    public func upload(
        data: Data,
        container: String,
        fileName: String,
        contentType: String
    ) async throws -> String {
        // Step 1: Get SAS token
        let sas = try await getSASToken(container: container, blobName: fileName, permissions: "w")

        // Step 2: Upload to blob storage using SAS URL
        guard let url = URL(string: sas.sasUrl) else {
            throw BLNetworkError.invalidURL(sas.sasUrl)
        }

        var request = URLRequest(url: url)
        request.httpMethod = "PUT"
        request.setValue(contentType, forHTTPHeaderField: "Content-Type")
        request.setValue("BlockBlob", forHTTPHeaderField: "x-ms-blob-type")
        request.httpBody = data
        request.timeoutInterval = 120

        let (_, response) = try await URLSession.shared.data(for: request)

        guard let http = response as? HTTPURLResponse,
              (200...299).contains(http.statusCode) else {
            throw BLNetworkError.httpError(statusCode: (response as? HTTPURLResponse)?.statusCode ?? 0, message: "Blob upload failed")
        }

        return sas.blobUrl
    }

    /// Convenience: upload audio data.
    public func uploadAudio(data: Data, fileName: String) async throws -> String {
        try await upload(data: data, container: "audio", fileName: fileName, contentType: "audio/wav")
    }

    /// Convenience: upload an attachment (image, document, etc.).
    public func uploadAttachment(data: Data, fileName: String, contentType: String) async throws -> String {
        try await upload(data: data, container: "attachments", fileName: fileName, contentType: contentType)
    }

    // MARK: - SAS Token

    /// Get a SAS token from platform-service.
    public func getSASToken(container: String, blobName: String, permissions: String = "r") async throws -> BLSASResponse {
        let body = [
            "container": container,
            "blobName": blobName,
            "permissions": permissions,
        ]
        return try await client.request(path: "/api/blob/sas", method: "POST", body: body, responseType: BLSASResponse.self)
    }
}
