package de.tsschulz.tt_tagebuch.app

import android.content.Context
import de.tsschulz.tt_tagebuch.BuildConfig
import de.tsschulz.tt_tagebuch.app.net.NetworkConnectivityHolder
import de.tsschulz.tt_tagebuch.shared.api.BillingApi
import de.tsschulz.tt_tagebuch.shared.api.CalendarHolidayApi
import de.tsschulz.tt_tagebuch.shared.api.AccidentApi
import de.tsschulz.tt_tagebuch.shared.api.ApiLogsApi
import de.tsschulz.tt_tagebuch.shared.api.ClubApprovalsApi
import de.tsschulz.tt_tagebuch.shared.api.ClickTtAccountApi
import de.tsschulz.tt_tagebuch.shared.api.ApiConfig
import de.tsschulz.tt_tagebuch.shared.api.AuthApi
import de.tsschulz.tt_tagebuch.shared.api.PublicAuthApi
import de.tsschulz.tt_tagebuch.shared.api.ClubTeamsApi
import de.tsschulz.tt_tagebuch.shared.api.ClubsApi
import de.tsschulz.tt_tagebuch.shared.api.DiaryApi
import de.tsschulz.tt_tagebuch.shared.api.DiaryMemberActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.DiaryMemberApi
import de.tsschulz.tt_tagebuch.shared.api.FeedbackApi
import de.tsschulz.tt_tagebuch.shared.api.GroupApi
import de.tsschulz.tt_tagebuch.shared.api.ParticipantsApi
import de.tsschulz.tt_tagebuch.shared.api.PredefinedActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.MatchesApi
import de.tsschulz.tt_tagebuch.shared.api.MemberActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.MemberGroupPhotosApi
import de.tsschulz.tt_tagebuch.shared.api.MemberTransferConfigApi
import de.tsschulz.tt_tagebuch.shared.api.MemberOrdersApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingCancellationApi
import de.tsschulz.tt_tagebuch.shared.api.MembersApi
import de.tsschulz.tt_tagebuch.shared.api.MyTischtennisApi
import de.tsschulz.tt_tagebuch.shared.api.OfficialTournamentsApi
import de.tsschulz.tt_tagebuch.shared.api.PermissionsApi
import de.tsschulz.tt_tagebuch.shared.api.SeasonsApi
import de.tsschulz.tt_tagebuch.shared.api.SessionApi
import de.tsschulz.tt_tagebuch.shared.api.SocketService
import de.tsschulz.tt_tagebuch.shared.api.TeamDocumentsApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingGroupsApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingStatsApi
import de.tsschulz.tt_tagebuch.shared.api.TrainingTimesApi
import de.tsschulz.tt_tagebuch.shared.api.TournamentsApi
import de.tsschulz.tt_tagebuch.shared.api.http.AndroidHttpClientEngineFactory
import de.tsschulz.tt_tagebuch.shared.api.http.AuthedHttpClient
import de.tsschulz.tt_tagebuch.shared.api.http.PublicHttpClient
import de.tsschulz.tt_tagebuch.shared.state.AndroidClubStorage
import de.tsschulz.tt_tagebuch.shared.state.AndroidLanguageStorage
import de.tsschulz.tt_tagebuch.shared.state.AndroidTokenStorage
import de.tsschulz.tt_tagebuch.shared.state.ApiLogsManager
import de.tsschulz.tt_tagebuch.shared.state.AuthManager
import de.tsschulz.tt_tagebuch.shared.state.ClubInternalTournamentsManager
import de.tsschulz.tt_tagebuch.shared.state.ClubManager
import de.tsschulz.tt_tagebuch.shared.state.DiaryManager
import de.tsschulz.tt_tagebuch.shared.state.LanguageManager
import de.tsschulz.tt_tagebuch.shared.state.MembersManager
import de.tsschulz.tt_tagebuch.shared.state.MutableTokenProvider
import de.tsschulz.tt_tagebuch.shared.state.OfficialTournamentsReadManager
import de.tsschulz.tt_tagebuch.shared.state.PendingApprovalsManager
import de.tsschulz.tt_tagebuch.shared.state.PermissionsAdminManager
import de.tsschulz.tt_tagebuch.shared.state.ScheduleManager
import de.tsschulz.tt_tagebuch.shared.state.TrainingStatsManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow

class AppDependencies(context: Context) {
    private val applicationJob = SupervisorJob()

    /**
     * Für Suspend-Aufrufe aus Button-Callbacks: überlebt das Verlassen der Composition
     * (z. B. Club wählen → anderer Screen), im Gegensatz zu [rememberCoroutineScope].
     */
    val applicationScope = CoroutineScope(applicationJob + Dispatchers.Main.immediate)
    val networkConnectivity = NetworkConnectivityHolder(context.applicationContext)
    val apiConfig = ApiConfig(baseUrl = BuildConfig.BACKEND_BASE_URL)
    val socketService = SocketService(BuildConfig.SOCKET_BASE_URL)
    val unauthorizedEvents = MutableStateFlow(0)
    private val tokenProvider = MutableTokenProvider()
    private val client = AuthedHttpClient(
        apiConfig = apiConfig,
        tokenProvider = tokenProvider,
        httpClientEngineFactory = AndroidHttpClientEngineFactory(),
        onUnauthorized = { unauthorizedEvents.value += 1 },
    )

    private val publicHttpClient = PublicHttpClient(
        apiConfig = apiConfig,
        httpClientEngineFactory = AndroidHttpClientEngineFactory(),
    )

    val publicAuthApi = PublicAuthApi(publicHttpClient)
    val feedbackApi = FeedbackApi(client)

    val authManager = AuthManager(
        tokenProvider = tokenProvider,
        tokenStorage = AndroidTokenStorage(context.applicationContext),
        authApi = AuthApi(client),
        sessionApi = SessionApi(client),
    )

    private val permissionsApi = PermissionsApi(client)
    val predefinedActivitiesApi = PredefinedActivitiesApi(client)

    val clubManager = ClubManager(
        clubStorage = AndroidClubStorage(context.applicationContext),
        clubsApi = ClubsApi(client),
        permissionsApi = permissionsApi,
    )

    val pendingApprovalsManager = PendingApprovalsManager(ClubApprovalsApi(client))
    val permissionsAdminManager = PermissionsAdminManager(permissionsApi)
    val apiLogsApi = ApiLogsApi(client)
    val apiLogsManager = ApiLogsManager(apiLogsApi)
    val tournamentsApi = TournamentsApi(client)
    val matchesApi = MatchesApi(client)
    val clubTeamsApi = ClubTeamsApi(client)
    val seasonsApi = SeasonsApi(client)
    val teamDocumentsApi = TeamDocumentsApi(client)
    val clubInternalTournamentsManager = ClubInternalTournamentsManager(tournamentsApi)
    val officialTournamentsApi = OfficialTournamentsApi(client)
    val officialTournamentsReadManager = OfficialTournamentsReadManager(officialTournamentsApi)
    val memberTransferConfigApi = MemberTransferConfigApi(client)
    val myTischtennisApi = MyTischtennisApi(client)
    val clickTtAccountApi = ClickTtAccountApi(client)
    val memberOrdersApi = MemberOrdersApi(client)
    val billingApi = BillingApi(client)
    val trainingCancellationApi = TrainingCancellationApi(client)
    val calendarHolidayApi = CalendarHolidayApi(client)

    val diaryManager = DiaryManager(
        DiaryApi(client),
        ParticipantsApi(client),
        GroupApi(client),
        DiaryMemberActivitiesApi(client),
        DiaryMemberApi(client),
        predefinedActivitiesApi,
        AccidentApi(client),
        MemberGroupPhotosApi(client),
    )
    private val trainingStatsApi = TrainingStatsApi(client)
    val membersApi = MembersApi(client)
    val membersManager = MembersManager(
        membersApi,
        TrainingGroupsApi(client),
        MemberActivitiesApi(client),
        TrainingTimesApi(client),
        trainingStatsApi,
    )
    val trainingStatsManager = TrainingStatsManager(trainingStatsApi)
    val scheduleManager = ScheduleManager(
        clubTeamsApi,
        matchesApi,
    )
    val languageManager = LanguageManager(AndroidLanguageStorage(context.applicationContext))
    val sessionApi = SessionApi(client)

    /** Header wie [AuthedHttpClient] (für Coil-Bilder, Downloads). */
    fun diaryAuthHeaders(): Map<String, String> = buildMap {
        tokenProvider.token?.let { put("authcode", it) }
        tokenProvider.username?.let { put("userid", it) }
    }
}
