package de.tsschulz.tt_tagebuch.shared.state

import de.tsschulz.tt_tagebuch.shared.api.ClubsApi
import de.tsschulz.tt_tagebuch.shared.api.PermissionsApi
import de.tsschulz.tt_tagebuch.shared.api.models.Club
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

class ClubManager(
    private val clubStorage: ClubStorage,
    private val clubsApi: ClubsApi,
    private val permissionsApi: PermissionsApi,
) {
    private val _state = MutableStateFlow(ClubState())
    val state: StateFlow<ClubState> = _state.asStateFlow()

    suspend fun hydrate() {
        val stored = clubStorage.loadCurrentClubId()
        if (stored == null) {
            _state.value = _state.value.copy(
                currentClubId = null,
                currentPermissions = null,
                isLoading = false,
                error = null,
            )
            return
        }
        _state.value = _state.value.copy(
            currentClubId = stored,
            isLoading = true,
            error = null,
        )
        try {
            val permissions = permissionsApi.getUserPermissions(stored)
            clubStorage.saveCurrentClubId(stored)
            _state.value = _state.value.copy(
                currentClubId = stored,
                currentPermissions = permissions,
                isLoading = false,
                error = null,
            )
        } catch (t: Throwable) {
            if (t is CancellationException) throw t
            _state.value = _state.value.copy(
                isLoading = false,
                error = t.toUserMessage("Keine Berechtigung oder Fehler beim Laden der Permissions"),
                currentPermissions = null,
                currentClubId = null,
            )
            clubStorage.saveCurrentClubId(null)
        }
    }

    suspend fun loadClubs() {
        _state.value = _state.value.copy(isLoading = true, error = null)
        try {
            val clubs = clubsApi.listClubs()
            _state.value = _state.value.copy(clubs = clubs, isLoading = false)
        } catch (t: Throwable) {
            if (t is CancellationException) throw t
            _state.value = _state.value.copy(isLoading = false, error = t.toUserMessage("Fehler beim Laden der Clubs"))
        }
    }

    suspend fun createClub(name: String) {
        val trimmed = name.trim()
        if (trimmed.isEmpty()) return
        _state.value = _state.value.copy(isLoading = true, error = null)
        try {
            val newClub = clubsApi.createClub(trimmed)
            loadClubs()
            selectClub(newClub.id)
        } catch (t: Throwable) {
            if (t is CancellationException) throw t
            _state.value = _state.value.copy(isLoading = false, error = t.toUserMessage("Verein konnte nicht erstellt werden"))
        }
    }

    suspend fun fetchClubDetail(clubId: Int): Club {
        return clubsApi.getClub(clubId)
    }

    suspend fun updateClubSettings(clubId: Int, body: UpdateClubSettingsBody) {
        clubsApi.updateClubSettings(clubId, body)
    }

    suspend fun selectClub(clubId: Int) {
        _state.value = _state.value.copy(isLoading = true, error = null)
        try {
            val permissions = permissionsApi.getUserPermissions(clubId)
            clubStorage.saveCurrentClubId(clubId)
            _state.value = _state.value.copy(
                currentClubId = clubId,
                currentPermissions = permissions,
                isLoading = false,
            )
        } catch (t: Throwable) {
            if (t is CancellationException) throw t
            _state.value = _state.value.copy(
                isLoading = false,
                error = t.toUserMessage("Keine Berechtigung oder Fehler beim Laden der Permissions"),
                currentPermissions = null,
                currentClubId = null,
            )
            clubStorage.saveCurrentClubId(null)
        }
    }

    suspend fun requestAccess(clubId: Int) {
        _state.value = _state.value.copy(isLoading = true, error = null)
        try {
            clubsApi.requestAccess(clubId)
            _state.value = _state.value.copy(isLoading = false)
        } catch (t: Throwable) {
            if (t is CancellationException) throw t
            _state.value = _state.value.copy(isLoading = false, error = t.toUserMessage("Access request fehlgeschlagen"))
        }
    }

    suspend fun clearSelection() {
        clubStorage.saveCurrentClubId(null)
        _state.value = _state.value.copy(currentClubId = null, currentPermissions = null)
    }
}
