//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation
import LibSignalClient
public import SignalRingRTC
public import SignalServiceKit

public struct CallLinkNotFoundError: Error {}

public class CallLinkFetcherImpl {
    private let sfuClient: SFUClient
    // Even though we never use this, we need to retain it to ensure
    // `sfuClient` continues to work properly.
    private let sfuClientHttpClient: AnyObject

    public init() {
        let httpClient = CallHTTPClient()
        self.sfuClient = SignalRingRTC.SFUClient(httpClient: httpClient.ringRtcHttpClient)
        self.sfuClientHttpClient = httpClient
    }

    public func readCallLink(
        _ rootKey: CallLinkRootKey,
        authCredential: SignalServiceKit.CallLinkAuthCredential,
    ) async throws -> SignalServiceKit.CallLinkState {
        let sfuUrl = DebugFlags.callingUseTestSFU.get() ? TSConstants.sfuTestURL : TSConstants.sfuURL
        let secretParams = CallLinkSecretParams.deriveFromRootKey(rootKey.bytes)
        let authCredentialPresentation = authCredential.present(callLinkParams: secretParams)
        do {
            return try await SignalServiceKit.CallLinkState(self.sfuClient.readCallLink(
                sfuUrl: sfuUrl,
                authCredentialPresentation: [UInt8](authCredentialPresentation.serialize()),
                linkRootKey: rootKey,
            ).unwrap())
        } catch where error.rawValue == 404 {
            throw CallLinkNotFoundError()
        }
    }
}

public struct SFUError: Error {
    let rawValue: UInt16
}

extension SFUResult {
    public func unwrap() throws(SFUError) -> Value {
        switch self {
        case .success(let value):
            return value
        case .failure(let errorCode):
            throw SFUError(rawValue: errorCode)
        }
    }
}
