package cy.hexor.furumi.di

import cy.hexor.furumi.data.local.AuthSessionStorage
import cy.hexor.furumi.data.remote.AccessTokenInterceptor
import cy.hexor.furumi.data.remote.AppClientInfo
import cy.hexor.furumi.data.remote.AuthAuthenticator
import cy.hexor.furumi.data.remote.AuthEndpoints
import cy.hexor.furumi.data.remote.api.AuthApi
import cy.hexor.furumi.data.remote.api.PlayerApi
import com.squareup.moshi.Moshi
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun provideAccessTokenInterceptor(
        sessionStorage: AuthSessionStorage,
        authEndpoints: AuthEndpoints,
        appClientInfo: AppClientInfo
    ): AccessTokenInterceptor {
        return AccessTokenInterceptor(sessionStorage, authEndpoints, appClientInfo)
    }

    @Provides
    @Singleton
    fun provideAuthAuthenticator(
        sessionStorage: AuthSessionStorage,
        authEndpoints: AuthEndpoints,
        authApiLazy: Lazy<AuthApi>
    ): AuthAuthenticator {
        return AuthAuthenticator(sessionStorage, authEndpoints, authApiLazy)
    }

    @Provides
    @Singleton
    fun provideOkHttpClient(
        accessTokenInterceptor: AccessTokenInterceptor,
        authAuthenticator: AuthAuthenticator
    ): OkHttpClient {
        val logging = HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BASIC
        }
        
        return OkHttpClient.Builder()
            .addInterceptor(accessTokenInterceptor)
            .addInterceptor(logging)
            .authenticator(authAuthenticator)
            .build()
    }

    @Provides
    @Singleton
    fun provideAuthApi(
        okHttpClient: OkHttpClient,
        moshi: Moshi
    ): AuthApi {
        // Auth requests use @Url, but Retrofit still requires an initial base URL.
        // The actual server URL is supplied per request.
        return Retrofit.Builder()
            .baseUrl("https://placeholder.com/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .build()
            .create(AuthApi::class.java)
    }

    @Provides
    @Singleton
    fun providePlayerApi(
        okHttpClient: OkHttpClient,
        moshi: Moshi
    ): PlayerApi {
        return Retrofit.Builder()
            .baseUrl("https://placeholder.com/")
            .client(okHttpClient)
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .build()
            .create(PlayerApi::class.java)
    }
}
