//
//  CallConstants.swift
//  humand
//
//  Created by Oleksandr Shumihin on 11/5/25.
//  Copyright © 2025 Humand. All rights reserved.
//

import Foundation

enum CallConstants {
  enum Localization {
    static let nameKey = "incoming_call_from"
    static let nameGroupKey = "incoming_call_from_group"
    static let unlockScreenVideoCallKey = "unlock_screen_video_call"
  }

  enum NotificationTypes {
    static let callInitialized = "CALL_INITIALIZED_V2"
    static let callMissed = "CALL_MISSED_V2"
    static let callAccepted = "CALL_ACCEPTED"
    static let callRejected = "CALL_REJECTED"
    static let callEnded = "CALL_ENDED"
    static let callJoinRequested = "CALL_JOIN_REQUESTED"
  }

  enum CallKeys {
    static let id = "id"
    static let name = "name"
    static let type = "type"
    static let isGroup = "isGroup"
    static let providerCallId = "providerCallId"
    static let initializationConfig = "initializationConfig"
  }

  enum RNEvents {
    static let callAccept = "CALL_ACCEPT_EVENT"
    static let callMute = "CALL_MUTE_EVENT"
    static let callEnd = "CALL_END_EVENT"
    static let callAudioActivated = "CALL_AUDIO_ACTIVATED_EVENT"
    static let callAudioRouteChanged = "CALL_AUDIO_ROUTE_CHANGED_EVENT"
    static let callStateChanged = "CALL_STATE_CHANGED_EVENT"
    static let callParticipantsChanged = "CALL_PARTICIPANTS_CHANGED_EVENT"
    static let callMediaStateChanged = "CALL_MEDIA_STATE_CHANGED_EVENT"
    static let callPipModeChanged = "CALL_PIP_MODE_CHANGED_EVENT"
    static let callObserverStarted = "CALLS_MOBILE_CALL_STARTED"
    static let callObserverAccepted = "CALLS_MOBILE_CALL_ACCEPTED"
    static let callObserverRejected = "CALLS_MOBILE_CALL_REJECTED"
    static let callObserverParticipantJoined = "CALLS_MOBILE_CALL_PARTICIPANT_JOINED"
    static let callObserverEnded = "CALLS_MOBILE_CALL_ENDED"
    static let callObserverRinging = "CALLS_MOBILE_CALL_RINGING"
  }

  enum Call {
    /// Microphone is disabled by default when participant count >= this threshold.
    static let micDisabledParticipantThreshold = 6
  }

  enum Retry {
    /// Default maximum retry attempts for async operations.
    static let defaultMaxAttempts = 3

    /// Default delay in seconds between retry attempts.
    static let defaultDelaySeconds: TimeInterval = 2.0
  }

  enum Timeout {
    static let outgoingCallSeconds: TimeInterval = 60.0
  }

  enum CallingState {
    static let idle = "idle"
    static let joining = "joining"
    static let joined = "joined"
    static let reconnecting = "reconnecting"
    static let reconnectingFailed = "reconnecting-failed"
  }

  /// Reasons forwarded to the SFU leave request (Stream SDK 1.46+).
  /// Backend analytics uses these to distinguish between leave flows.
  enum LeaveReason {
    static let userInitiated = "user_initiated"
    static let remoteEnded = "remote_ended"
    static let calleeRejected = "callee_rejected"
    static let outgoingTimeout = "outgoing_timeout"
    static let reconnectionFailed = "reconnection_failed"
    static let cleanup = "cleanup"
  }

  enum Api {
    static let tag = "ApiService"
    static let tokensKey = "TOKENS"
    static let accessTokenKey = "accessToken"
    static let refreshTokenKey = "refreshToken"
    static let refreshTokenURLPath = "/auth/refresh"
    static let tokenExpired = "TOKEN_EXPIRED"

    /// Maximum retry attempts for API requests.
    static let maxRetries = 3

    /// Delay in nanoseconds between API request retries (1 second).
    static let retryDelayNs: UInt64 = 1_000_000_000

    enum Headers {
      static let authorization = "Authorization"
      static let contentType = "Content-Type"
      static let contentTypeValue = "application/json"
      static let origin = "x-humand-origin"
      static let originValue = "app"
      static let deviceType = "x-device-type"
      static let deviceTypeValue = "ios"
      static let deviceVersion = "x-device-version"
      static let humandDeviceVersion = "x-humand-device-version"
    }
  }

  enum ApiError: Error, LocalizedError {
    case invalidUrl
    case missingTokens
    case tokenRefreshFailed
    case requestFailed(statusCode: Int)
    case decodingFailed

    var errorDescription: String? {
      switch self {
      case .invalidUrl:
        return "Could not create URL"
      case .missingTokens:
        return "Could not get tokens"
      case .tokenRefreshFailed:
        return "Token refresh failed"
      case .requestFailed(let statusCode):
        return "Request failed with status code: \(statusCode)"
      case .decodingFailed:
        return "Failed to decode response"
      }
    }
  }
}
