package com.bitwarden.authenticator.data.platform.datasource.network.di

import com.bitwarden.authenticator.BuildConfig
import com.bitwarden.authenticator.data.auth.datasource.disk.AuthDiskSource
import com.bitwarden.authenticator.data.platform.datasource.network.util.HEADER_VALUE_CLIENT_NAME
import com.bitwarden.authenticator.data.platform.datasource.network.util.HEADER_VALUE_CLIENT_VERSION
import com.bitwarden.authenticator.data.platform.datasource.network.util.HEADER_VALUE_USER_AGENT
import com.bitwarden.network.BitwardenServiceClient
import com.bitwarden.network.bitwardenServiceClient
import com.bitwarden.network.interceptor.AuthTokenProvider
import com.bitwarden.network.interceptor.BaseUrlsProvider
import com.bitwarden.network.model.AuthTokenData
import com.bitwarden.network.model.BitwardenServiceClientConfig
import com.bitwarden.network.model.NetworkCookie
import com.bitwarden.network.provider.CookieProvider
import com.bitwarden.network.provider.PermissionProvider
import com.bitwarden.network.service.ConfigService
import com.bitwarden.network.service.DownloadService
import com.bitwarden.network.ssl.CertificateProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json
import java.net.Socket
import java.security.Principal
import java.security.PrivateKey
import java.security.cert.X509Certificate
import java.time.Clock
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
/**
 * This class provides network-related functionality for the application.
 * It initializes and configures the networking components.
 */
object PlatformNetworkModule {
    @Provides
    @Singleton
    fun providesConfigService(
        bitwardenServiceClient: BitwardenServiceClient,
    ): ConfigService = bitwardenServiceClient.configService

    @Provides
    @Singleton
    fun provideBitwardenServiceClientConfig(
        baseUrlsProvider: BaseUrlsProvider,
        authDiskSource: AuthDiskSource,
        clock: Clock,
    ): BitwardenServiceClientConfig =
        BitwardenServiceClientConfig(
            clock = clock,
            appIdProvider = authDiskSource,
            clientData = BitwardenServiceClientConfig.ClientData(
                userAgent = HEADER_VALUE_USER_AGENT,
                clientName = HEADER_VALUE_CLIENT_NAME,
                clientVersion = HEADER_VALUE_CLIENT_VERSION,
            ),
            baseUrlsProvider = baseUrlsProvider,
            enableHttpBodyLogging = BuildConfig.DEBUG,
            authTokenProvider = object : AuthTokenProvider {
                override fun getAuthTokenDataOrNull(): AuthTokenData? = null

                override fun getAuthTokenDataOrNull(userId: String): AuthTokenData? = null
            },
            certificateProvider = object : CertificateProvider {
                override fun chooseClientAlias(
                    keyType: Array<out String>?,
                    issuers: Array<out Principal>?,
                    socket: Socket?,
                ): String = ""

                override fun getCertificateChain(alias: String?): Array<X509Certificate>? = null

                override fun getPrivateKey(alias: String?): PrivateKey? = null
            },
            cookieProvider = object : CookieProvider {
                override val errorMessageString: String get() = "Error"

                override fun needsBootstrap(hostname: String): Boolean = false

                override fun getCookies(hostname: String): List<NetworkCookie> = emptyList()

                override fun acquireCookies(hostname: String): Unit = Unit
            },
            permissionProvider = object : PermissionProvider {
                override val errorMessageString: String get() = "Error"

                override val hasLocalNetworkAccessPermission: Boolean get() = false

                override fun acquireLocalNetworkAccessPermission(): Unit = Unit
            },
        )

    @Provides
    @Singleton
    fun provideBitwardenServiceClient(
        serviceClientConfig: BitwardenServiceClientConfig,
        json: Json,
    ): BitwardenServiceClient = bitwardenServiceClient(
        config = serviceClientConfig,
        json = json,
    )

    @Provides
    @Singleton
    fun provideDownloadService(
        bitwardenServiceClient: BitwardenServiceClient,
    ): DownloadService = bitwardenServiceClient.downloadService
}
