package de.trainingstagebuch.app.repository

import de.trainingstagebuch.app.network.ApiService
import de.trainingstagebuch.app.network.BaseResponse
import de.trainingstagebuch.app.network.CreateClubRequest
import de.trainingstagebuch.app.network.RegisterRequest
import de.trainingstagebuch.app.network.SocketEvent
import de.trainingstagebuch.app.network.SocketEventType
import de.trainingstagebuch.app.network.SocketManager
import de.trainingstagebuch.app.utils.AppErrorUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.put
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.toRequestBody
import retrofit2.HttpException

class TrainingstagebuchRepository(
    private val apiService: ApiService
) {
    private val socketScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
    private val _socketDomainEvents = MutableSharedFlow<DomainSocketEvent>(
        replay = 0,
        extraBufferCapacity = 64
    )
    val socketDomainEvents: SharedFlow<DomainSocketEvent> = _socketDomainEvents.asSharedFlow()

    init {
        socketScope.launch {
            SocketManager.events.collect { socketEvent ->
                _socketDomainEvents.emit(mapSocketEvent(socketEvent))
            }
        }
    }

    private fun mapSocketEvent(socketEvent: SocketEvent): DomainSocketEvent {
        val type = when (socketEvent.type) {
            SocketEventType.ParticipantAdded -> DomainSocketEventType.ParticipantAdded
            SocketEventType.ParticipantRemoved -> DomainSocketEventType.ParticipantRemoved
            SocketEventType.ParticipantUpdated -> DomainSocketEventType.ParticipantUpdated
            SocketEventType.DiaryNoteAdded -> DomainSocketEventType.DiaryNoteAdded
            SocketEventType.DiaryNoteUpdated -> DomainSocketEventType.DiaryNoteUpdated
            SocketEventType.DiaryNoteDeleted -> DomainSocketEventType.DiaryNoteDeleted
            SocketEventType.DiaryTagAdded -> DomainSocketEventType.DiaryTagAdded
            SocketEventType.DiaryTagRemoved -> DomainSocketEventType.DiaryTagRemoved
            SocketEventType.DiaryDateUpdated -> DomainSocketEventType.DiaryDateUpdated
            SocketEventType.ActivityMemberAdded -> DomainSocketEventType.ActivityMemberAdded
            SocketEventType.ActivityMemberRemoved -> DomainSocketEventType.ActivityMemberRemoved
            SocketEventType.ActivityChanged -> DomainSocketEventType.ActivityChanged
            SocketEventType.MemberChanged -> DomainSocketEventType.MemberChanged
            SocketEventType.GroupChanged -> DomainSocketEventType.GroupChanged
            SocketEventType.TournamentChanged -> DomainSocketEventType.TournamentChanged
            SocketEventType.ScheduleMatchUpdated -> DomainSocketEventType.ScheduleMatchUpdated
            SocketEventType.ScheduleMatchReportSubmitted -> DomainSocketEventType.ScheduleMatchReportSubmitted
            SocketEventType.Unknown -> DomainSocketEventType.Unknown
        }
        return DomainSocketEvent(
            type = type,
            rawType = socketEvent.rawType,
            payload = socketEvent.payload
        )
    }

    suspend fun checkSession(): BaseResponse<JsonElement> = apiService.getSessionStatus()
    suspend fun getClubs(): JsonElement = apiService.getClubs()
    suspend fun loadHomeData(): HomeResult {
        return try {
            val clubs = apiService.getClubs()
            HomeResult.Success(RepositoryMappers.mapClubsToHomeData(clubs))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            HomeResult.Error(AppErrorUtils.backendOrThrowable(parsed?.message, e))
        } catch (e: Exception) {
            HomeResult.Error(AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createClub(name: String): CreateClubResult {
        return try {
            val response = apiService.createClub(CreateClubRequest(name = name))
            val createdClubId = extractCreatedClubId(response)
            CreateClubResult.Success(createdClubId = createdClubId)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            CreateClubResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            CreateClubResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadClub(clubId: String): ClubResult {
        return try {
            val response = apiService.getClub(clubId)
            val obj = response as? JsonObject ?: return ClubResult.Error(message = AppErrorUtils.unknown())
            ClubResult.Success(data = RepositoryMappers.mapClubDetails(obj))
        } catch (e: HttpException) {
            if (e.code() == 403) {
                val raw = e.response()?.errorBody()?.string()
                val parsedObj = raw?.let(de.trainingstagebuch.app.utils.JsonSafeUtils::parseObject)
                val status = parsedObj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "status") }
                val requested = status.equals("requested", ignoreCase = true)
                val message = parsedObj?.let {
                    de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "message", "error")
                }
                return ClubResult.AccessDenied(
                    requested = requested,
                    message = message
                )
            }
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun requestClubAccess(clubId: String): ClubAccessRequestResult {
        return try {
            val response = apiService.requestClubAccess(clubId = clubId)
            if (response.success == false) {
                ClubAccessRequestResult.Error(
                    code = response.code,
                    message = response.error ?: response.message
                )
            } else {
                ClubAccessRequestResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            if (e.code() == 409) {
                return ClubAccessRequestResult.AlreadyRequested(
                    message = AppErrorUtils.backendOrThrowable(null, e)
                )
            }
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubAccessRequestResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubAccessRequestResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadPendingApprovals(clubId: String): PendingApprovalsResult {
        return try {
            val response = apiService.getPendingApprovals(clubId = clubId)
            PendingApprovalsResult.Success(users = RepositoryMappers.mapPendingApprovals(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PendingApprovalsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PendingApprovalsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun approvePendingUser(clubId: String, userId: String): ClubActionResult {
        return try {
            val response = apiService.approveClubAccess(
                buildJsonObject {
                    put("clubid", clubId)
                    put("userid", userId)
                }
            )
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun rejectPendingUser(clubId: String, userId: String): ClubActionResult {
        return try {
            val response = apiService.rejectClubAccess(
                buildJsonObject {
                    put("clubid", clubId)
                    put("userid", userId)
                }
            )
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadClubSettings(clubId: String): ClubSettingsResult {
        return try {
            val response = apiService.getClub(clubId)
            val obj = response as? JsonObject ?: return ClubSettingsResult.Error(message = AppErrorUtils.unknown())
            val settings = RepositoryMappers.mapClubSettings(obj)
            ClubSettingsResult.Success(settings = settings)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubSettingsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubSettingsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun saveClubSettings(
        clubId: String,
        greetingText: String,
        associationMemberNumber: String
    ): ClubSettingsActionResult {
        return try {
            val response = apiService.updateClubSettings(
                clubId = clubId,
                body = buildJsonObject {
                    put("greetingText", greetingText)
                    put("associationMemberNumber", associationMemberNumber)
                }
            )
            if (response.success == false) {
                ClubSettingsActionResult.Error(
                    code = response.code,
                    message = response.error ?: response.message
                )
            } else {
                ClubSettingsActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubSettingsActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubSettingsActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadClubTrainingGroups(clubId: String): ClubTrainingGroupsResult {
        return try {
            val response = apiService.getTrainingGroups(clubId = clubId)
            ClubTrainingGroupsResult.Success(groups = RepositoryMappers.mapClubTrainingGroups(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubTrainingGroupsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubTrainingGroupsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createClubTrainingGroup(clubId: String, name: String): ClubActionResult {
        return try {
            val response = apiService.createTrainingGroup(
                clubId = clubId,
                body = buildJsonObject { put("name", name) }
            )
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteClubTrainingGroup(clubId: String, groupId: String): ClubActionResult {
        return try {
            val response = apiService.deleteTrainingGroup(clubId = clubId, groupId = groupId)
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateClubTrainingGroup(clubId: String, groupId: String, name: String): ClubActionResult {
        return try {
            val response = apiService.updateTrainingGroup(
                clubId = clubId,
                groupId = groupId,
                body = buildJsonObject { put("name", name) }
            )
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadClubTrainingTimes(clubId: String): ClubTrainingTimesResult {
        return try {
            val response = apiService.getTrainingTimes(clubId = clubId)
            ClubTrainingTimesResult.Success(groups = RepositoryMappers.mapClubTrainingTimeGroups(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubTrainingTimesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubTrainingTimesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createClubTrainingTime(
        clubId: String,
        trainingGroupId: String,
        weekday: Int,
        startTime: String,
        endTime: String
    ): ClubActionResult {
        return try {
            val response = apiService.createTrainingTime(
                clubId = clubId,
                body = buildJsonObject {
                    put("trainingGroupId", trainingGroupId)
                    put("weekday", weekday)
                    put("startTime", startTime)
                    put("endTime", endTime)
                }
            )
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteClubTrainingTime(clubId: String, timeId: String): ClubActionResult {
        return try {
            val response = apiService.deleteTrainingTime(clubId = clubId, timeId = timeId)
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateClubTrainingTime(
        clubId: String,
        timeId: String,
        weekday: Int,
        startTime: String,
        endTime: String
    ): ClubActionResult {
        return try {
            val response = apiService.updateTrainingTime(
                clubId = clubId,
                timeId = timeId,
                body = buildJsonObject {
                    put("weekday", weekday)
                    put("startTime", startTime)
                    put("endTime", endTime)
                }
            )
            if (response.success == false) {
                ClubActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMembers(clubId: String, showAll: Boolean = true): MembersResult {
        return try {
            val members = apiService.getClubMembers(clubId = clubId, showAll = showAll)
            MembersResult.Success(RepositoryMappers.mapMembersToMemberItems(members))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MembersResult.Error(AppErrorUtils.backendOrThrowable(parsed?.message, e))
        } catch (e: Exception) {
            MembersResult.Error(AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadNotApprovedMembers(clubId: String): MembersResult {
        return try {
            val members = apiService.getNotApprovedMembers(clubId = clubId)
            MembersResult.Success(RepositoryMappers.mapMembersToMemberItems(members))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MembersResult.Error(AppErrorUtils.backendOrThrowable(parsed?.message, e))
        } catch (e: Exception) {
            MembersResult.Error(AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadDiaryDates(clubId: String): DiaryDatesResult {
        return try {
            val dates = apiService.getDiaryDates(clubId = clubId)
            DiaryDatesResult.Success(dates = RepositoryMappers.mapDiaryDates(dates))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryDatesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryDatesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createDiaryDate(
        clubId: String,
        date: String,
        trainingStart: String?,
        trainingEnd: String?
    ): DiaryCreateDateResult {
        return try {
            val response = apiService.createDiaryDate(
                clubId = clubId,
                body = buildJsonObject {
                    put("date", date)
                    put("trainingStart", trainingStart)
                    put("trainingEnd", trainingEnd)
                }
            )
            val created = RepositoryMappers.mapDiaryDate(response)
                ?: (response as? JsonObject)?.get("data")?.let(RepositoryMappers::mapDiaryDate)
                ?: return DiaryCreateDateResult.Error(code = null, message = AppErrorUtils.unknown())
            DiaryCreateDateResult.Success(entry = created)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryCreateDateResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryCreateDateResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateDiaryTrainingTime(
        clubId: String,
        dateId: String,
        trainingStart: String?,
        trainingEnd: String?
    ): DiaryActionResult {
        return try {
            val response = apiService.updateDiaryTrainingTime(
                clubId = clubId,
                body = buildJsonObject {
                    put("dateId", dateId)
                    put("trainingStart", trainingStart)
                    put("trainingEnd", trainingEnd)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteDiaryDate(clubId: String, dateId: String): DiaryActionResult {
        return try {
            val response = apiService.deleteDiaryDate(clubId = clubId, dateId = dateId)
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadParticipants(dateId: String): DiaryParticipantsResult {
        return try {
            val participants = apiService.getParticipants(dateId = dateId)
            DiaryParticipantsResult.Success(
                participants = RepositoryMappers.mapDiaryParticipants(participants)
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryParticipantsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryParticipantsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addParticipant(dateId: String, memberId: String): DiaryParticipantActionResult {
        return try {
            val response = apiService.addParticipant(
                buildJsonObject {
                    put("diaryDateId", dateId)
                    put("memberId", memberId)
                }
            )
            val participant = RepositoryMappers.mapDiaryParticipants(
                buildJsonArray { add(response) }
            ).firstOrNull()
            DiaryParticipantActionResult.Success(participant = participant)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryParticipantActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryParticipantActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun removeParticipant(dateId: String, memberId: String): DiaryActionResult {
        return try {
            val response = apiService.removeParticipant(
                buildJsonObject {
                    put("diaryDateId", dateId)
                    put("memberId", memberId)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadActivities(dateId: String): DiaryActivitiesResult {
        return try {
            val activities = apiService.getActivities(dateId = dateId)
            DiaryActivitiesResult.Success(activities = RepositoryMappers.mapDiaryActivities(activities))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActivitiesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActivitiesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addActivity(
        dateId: String,
        description: String
    ): DiaryAddActivityResult {
        return try {
            val response = apiService.addActivity(
                buildJsonObject {
                    put("diaryDateId", dateId)
                    put("description", description)
                    put("tags", buildJsonArray { })
                }
            )
            val created = RepositoryMappers.mapDiaryActivities(response).firstOrNull()
                ?: RepositoryMappers.mapDiaryActivity(response)
            if (created == null) {
                DiaryAddActivityResult.Error(code = null, message = AppErrorUtils.unknown())
            } else {
                DiaryAddActivityResult.Success(activity = created)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryAddActivityResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryAddActivityResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadDiaryMemberNotes(
        clubId: String,
        diaryDateId: String,
        memberId: String
    ): MemberNotesResult {
        return try {
            val notes = apiService.getDiaryMemberNotes(
                clubId = clubId,
                query = mapOf("diaryDateId" to diaryDateId, "memberId" to memberId)
            )
            MemberNotesResult.Success(notes = RepositoryMappers.mapMemberNotes(notes))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberNotesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberNotesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addDiaryMemberNote(
        clubId: String,
        diaryDateId: String,
        memberId: String,
        content: String
    ): DiaryActionResult {
        return try {
            apiService.addDiaryMemberNote(
                clubId = clubId,
                body = buildJsonObject {
                    put("memberId", memberId)
                    put("diaryDateId", diaryDateId)
                    put("content", content)
                }
            )
            DiaryActionResult.Success(message = null)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteDiaryMemberNote(clubId: String, noteId: String): DiaryActionResult {
        return try {
            apiService.deleteDiaryMemberNote(clubId = clubId, noteId = noteId)
            DiaryActionResult.Success(message = null)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTags(): DiaryTagsResult {
        return try {
            val tags = apiService.getTags()
            DiaryTagsResult.Success(tags = RepositoryMappers.mapTags(tags))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryTagsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryTagsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createTag(name: String): DiaryCreateTagResult {
        return try {
            val response = apiService.createTag(
                buildJsonObject {
                    put("name", name)
                }
            )
            val created = RepositoryMappers.mapTag(response)
                ?: RepositoryMappers.mapTags(response).firstOrNull()
            if (created == null) {
                DiaryCreateTagResult.Error(code = null, message = AppErrorUtils.unknown())
            } else {
                DiaryCreateTagResult.Success(tag = created)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryCreateTagResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryCreateTagResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addTagToDiaryDate(clubId: String, diaryDateId: String, tagId: String): DiaryActionResult {
        return try {
            val response = apiService.addTagToDiaryDate(
                clubId = clubId,
                body = buildJsonObject {
                    put("diaryDateId", diaryDateId)
                    put("tagId", tagId)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun removeTagFromDiaryDate(clubId: String, diaryDateId: String, tagId: String): DiaryActionResult {
        return try {
            val response = apiService.deleteTagFromDiaryDate(
                clubId = clubId,
                body = buildJsonObject {
                    put("diaryDateId", diaryDateId)
                    put("tagId", tagId)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadDiaryPlan(clubId: String, dateId: String): DiaryPlanResult {
        return try {
            val response = apiService.getDiaryDateActivities(clubId = clubId, dateId = dateId)
            DiaryPlanResult.Success(items = RepositoryMappers.mapDiaryPlanItems(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryPlanResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryPlanResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addDiaryPlanItem(
        clubId: String,
        dateId: String,
        activity: String,
        orderId: Int
    ): DiaryActionResult {
        return try {
            val response = apiService.createDiaryDateActivity(
                clubId = clubId,
                body = buildJsonObject {
                    put("diaryDateId", dateId)
                    put("activity", activity)
                    put("isTimeblock", false)
                    put("duration", "")
                    put("durationText", "")
                    put("orderId", orderId)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateDiaryPlanItem(
        clubId: String,
        planItemId: String,
        activity: String
    ): DiaryActionResult {
        return try {
            val response = apiService.updateDiaryDateActivity(
                clubId = clubId,
                activityId = planItemId,
                body = buildJsonObject {
                    put("customActivityName", activity)
                    put("duration", "")
                    put("durationText", "")
                    put("groupId", null)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteDiaryPlanItem(clubId: String, planItemId: String): DiaryActionResult {
        return try {
            val response = apiService.deleteDiaryDateActivity(clubId = clubId, activityId = planItemId)
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateDiaryPlanItemOrder(clubId: String, planItemId: String, order: Int): DiaryActionResult {
        return try {
            val response = apiService.updateDiaryDateActivityOrder(
                clubId = clubId,
                activityId = planItemId,
                body = buildJsonObject {
                    put("order", order)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadDiaryGroups(clubId: String, dateId: String): DiaryGroupsResult {
        return try {
            val response = apiService.getGroups(clubId = clubId, dateId = dateId)
            DiaryGroupsResult.Success(groups = RepositoryMappers.mapDiaryGroups(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryGroupsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryGroupsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateParticipantGroup(dateId: String, memberId: String, groupId: String?): DiaryActionResult {
        return try {
            val response = apiService.updateParticipantGroup(
                dateId = dateId,
                memberId = memberId,
                body = buildJsonObject {
                    put("groupId", groupId)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createDiaryGroup(clubId: String, dateId: String, name: String, lead: String): DiaryActionResult {
        return try {
            val response = apiService.createGroup(
                buildJsonObject {
                    put("clubid", clubId)
                    put("dateid", dateId)
                    put("name", name)
                    put("lead", lead)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateDiaryGroup(groupId: String, clubId: String, dateId: String, name: String, lead: String): DiaryActionResult {
        return try {
            val response = apiService.updateGroup(
                groupId = groupId,
                body = buildJsonObject {
                    put("clubid", clubId)
                    put("dateid", dateId)
                    put("name", name)
                    put("lead", lead)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteDiaryGroup(groupId: String, clubId: String, dateId: String): DiaryActionResult {
        return try {
            val response = apiService.deleteGroupWithBody(
                groupId = groupId,
                body = buildJsonObject {
                    put("clubid", clubId)
                    put("dateid", dateId)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createDiaryGroupActivity(
        clubId: String,
        dateId: String,
        groupId: String,
        activity: String,
        predefinedActivityId: String?
    ): DiaryActionResult {
        return try {
            val response = apiService.createGroupActivity(
                buildJsonObject {
                    put("clubId", clubId)
                    put("diaryDateId", dateId)
                    put("groupId", groupId)
                    put("activity", activity)
                    if (!predefinedActivityId.isNullOrBlank()) {
                        put("predefinedActivityId", predefinedActivityId)
                    }
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadActivityParticipantIds(clubId: String, activityId: String): DiaryActivityParticipantsResult {
        return try {
            val response = apiService.getDiaryMemberActivities(clubId = clubId, diaryDateActivityId = activityId)
            DiaryActivityParticipantsResult.Success(participantIds = RepositoryMappers.mapParticipantIds(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActivityParticipantsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActivityParticipantsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun assignActivityParticipants(clubId: String, activityId: String, participantIds: List<String>): DiaryActionResult {
        return try {
            val response = apiService.setDiaryMemberActivities(
                clubId = clubId,
                diaryDateActivityId = activityId,
                body = buildJsonObject {
                    put(
                        "participantIds",
                        buildJsonArray {
                            participantIds.forEach { id -> add(JsonPrimitive(id)) }
                        }
                    )
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun removeActivityParticipant(clubId: String, activityId: String, participantId: String): DiaryActionResult {
        return try {
            val response = apiService.deleteDiaryMemberActivity(
                clubId = clubId,
                diaryDateActivityId = activityId,
                participantId = participantId
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createAccident(clubId: String, dateId: String, accident: String): DiaryActionResult {
        return try {
            val response = apiService.createAccident(
                buildJsonObject {
                    put("clubId", clubId)
                    put("diaryDateId", dateId)
                    put("accident", accident)
                }
            )
            if (response.success == false) {
                DiaryActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                DiaryActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadAccidents(clubId: String, dateId: String): DiaryAccidentsResult {
        return try {
            val response = apiService.getAccidents(clubId = clubId, dateId = dateId)
            DiaryAccidentsResult.Success(items = RepositoryMappers.mapAccidents(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            DiaryAccidentsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            DiaryAccidentsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMemberActivityStats(clubId: String, memberId: String): MemberActivityStatsResult {
        return try {
            val stats = apiService.getMemberActivities(clubId = clubId, memberId = memberId, period = "all")
            val last = apiService.getMemberLastParticipations(clubId = clubId, memberId = memberId, limit = 3)
            MemberActivityStatsResult.Success(
                stats = RepositoryMappers.mapMemberActivityStats(stats),
                lastParticipations = RepositoryMappers.mapLastParticipations(last)
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberActivityStatsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberActivityStatsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun searchPredefinedActivities(term: String, limit: Int = 10): PredefinedActivitiesResult {
        return try {
            val response = apiService.searchPredefinedActivities(query = term, limit = limit)
            PredefinedActivitiesResult.Success(items = RepositoryMappers.mapPredefinedActivities(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivitiesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivitiesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadPredefinedActivities(): PredefinedActivitiesResult {
        return try {
            val response = apiService.getPredefinedActivities()
            PredefinedActivitiesResult.Success(items = RepositoryMappers.mapPredefinedActivities(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivitiesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivitiesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadPredefinedActivity(activityId: String): PredefinedActivityDetailResult {
        return try {
            val response = apiService.getPredefinedActivity(activityId)
            val obj = response as? JsonObject ?: return PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            val mapped = RepositoryMappers.mapPredefinedActivity(obj)
                ?: return PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            PredefinedActivityDetailResult.Success(item = mapped)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivityDetailResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createPredefinedActivity(input: PredefinedActivityInput): PredefinedActivityDetailResult {
        return try {
            val response = apiService.createPredefinedActivity(
                buildJsonObject {
                    put("name", input.name)
                    put("code", input.code)
                    put("duration", input.duration)
                    put("durationText", input.durationText)
                    put("description", input.description)
                    put("imageLink", input.imageLink)
                    if (!input.drawingData.isNullOrBlank()) {
                        put("drawingData", input.drawingData)
                    }
                }
            )
            val obj = response as? JsonObject ?: return PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            val mapped = RepositoryMappers.mapPredefinedActivity(obj)
                ?: return PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            PredefinedActivityDetailResult.Success(item = mapped)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivityDetailResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updatePredefinedActivity(activityId: String, input: PredefinedActivityInput): PredefinedActivityDetailResult {
        return try {
            val response = apiService.updatePredefinedActivity(
                id = activityId,
                body = buildJsonObject {
                    put("name", input.name)
                    put("code", input.code)
                    put("duration", input.duration)
                    put("durationText", input.durationText)
                    put("description", input.description)
                    put("imageLink", input.imageLink)
                    if (!input.drawingData.isNullOrBlank()) {
                        put("drawingData", input.drawingData)
                    }
                }
            )
            val obj = response as? JsonObject ?: return PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            val mapped = RepositoryMappers.mapPredefinedActivity(obj)
                ?: return PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            PredefinedActivityDetailResult.Success(item = mapped)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivityDetailResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivityDetailResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun mergePredefinedActivities(sourceId: String, targetId: String): PredefinedActivityActionResult {
        return try {
            val response = apiService.mergePredefinedActivities(
                buildJsonObject {
                    put("sourceId", sourceId)
                    put("targetId", targetId)
                }
            )
            if (response.success == false) {
                PredefinedActivityActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                PredefinedActivityActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivityActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivityActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deduplicatePredefinedActivities(): PredefinedActivityActionResult {
        return try {
            val response = apiService.deduplicatePredefinedActivities(buildJsonObject {})
            if (response.success == false) {
                PredefinedActivityActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                PredefinedActivityActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivityActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivityActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deletePredefinedActivityImage(activityId: String, imageId: String): PredefinedActivityActionResult {
        return try {
            val response = apiService.deletePredefinedActivityImage(id = activityId, imageId = imageId)
            if (response.success == false) {
                PredefinedActivityActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                PredefinedActivityActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PredefinedActivityActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PredefinedActivityActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTrainingStats(clubId: String): TrainingStatsResult {
        return try {
            val response = apiService.getTrainingStats(clubId)
            val obj = response as? JsonObject ?: return TrainingStatsResult.Error(code = null, message = AppErrorUtils.unknown())
            TrainingStatsResult.Success(data = RepositoryMappers.mapTrainingStats(obj))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TrainingStatsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TrainingStatsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadScheduleTeams(clubId: String, seasonId: String? = null): ScheduleTeamsResult {
        return try {
            val response = apiService.getClubTeams(clubId = clubId, seasonId = seasonId)
            ScheduleTeamsResult.Success(teams = RepositoryMappers.mapScheduleTeams(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ScheduleTeamsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ScheduleTeamsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadScheduleMatches(
        clubId: String,
        leagueId: String? = null,
        seasonId: String? = null
    ): ScheduleMatchesResult {
        return try {
            val response = if (leagueId.isNullOrBlank()) {
                apiService.getLeagueMatches(clubId = clubId, seasonId = seasonId)
            } else {
                apiService.getMatchesForLeague(clubId = clubId, leagueId = leagueId)
            }
            ScheduleMatchesResult.Success(matches = RepositoryMappers.mapScheduleMatches(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ScheduleMatchesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ScheduleMatchesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadLeagueTable(clubId: String, leagueId: String): ScheduleLeagueTableResult {
        return try {
            val response = apiService.getLeagueTable(clubId = clubId, leagueId = leagueId)
            ScheduleLeagueTableResult.Success(rows = RepositoryMappers.mapLeagueTable(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ScheduleLeagueTableResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ScheduleLeagueTableResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateMatchPlayers(
        matchId: String,
        clubId: String,
        playersReady: List<String>,
        playersPlanned: List<String>,
        playersPlayed: List<String>
    ): ScheduleActionResult {
        return try {
            val response = apiService.updateMatchPlayers(
                matchId = matchId,
                body = buildJsonObject {
                    put("clubId", clubId)
                    put("playersReady", buildJsonArray { playersReady.forEach { add(JsonPrimitive(it)) } })
                    put("playersPlanned", buildJsonArray { playersPlanned.forEach { add(JsonPrimitive(it)) } })
                    put("playersPlayed", buildJsonArray { playersPlayed.forEach { add(JsonPrimitive(it)) } })
                }
            )
            if (response.success == false) {
                ScheduleActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ScheduleActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ScheduleActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ScheduleActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTournaments(clubId: String, type: String? = null): TournamentListResult {
        return try {
            val response = apiService.getTournaments(clubId = clubId, type = type)
            TournamentListResult.Success(items = RepositoryMappers.mapTournaments(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentListResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentListResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTournament(clubId: String, tournamentId: String): TournamentDetailResult {
        return try {
            val response = apiService.getTournament(clubId = clubId, tournamentId = tournamentId)
            val obj = response as? JsonObject ?: return TournamentDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            val item = RepositoryMappers.mapTournament(obj)
                ?: return TournamentDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            TournamentDetailResult.Success(item = item)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentDetailResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentDetailResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createTournament(
        clubId: String,
        name: String,
        date: String,
        winningSets: Int
    ): TournamentActionResult {
        return try {
            val response = apiService.createTournament(
                buildJsonObject {
                    put("clubId", clubId)
                    put("name", name)
                    put("date", date)
                    put("winningSets", winningSets)
                }
            )
            if (response.success == false) {
                TournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                TournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createMiniTournament(
        clubId: String,
        location: String,
        date: String,
        year: Int,
        winningSets: Int
    ): TournamentActionResult {
        return try {
            val response = apiService.createMiniTournament(
                buildJsonObject {
                    put("clubId", clubId)
                    put("ort", location)
                    put("date", date)
                    put("year", year)
                    put("winningSets", winningSets)
                }
            )
            if (response.success == false) {
                TournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                TournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateTournamentConfig(
        clubId: String,
        tournamentId: String,
        name: String,
        date: String?,
        winningSets: Int,
        numberOfTables: Int?,
        isGroupTournament: Boolean
    ): TournamentActionResult {
        return try {
            val response = apiService.updateTournament(
                clubId = clubId,
                tournamentId = tournamentId,
                body = buildJsonObject {
                    put("name", name)
                    if (!date.isNullOrBlank()) put("date", date)
                    put("winningSets", winningSets)
                    if (numberOfTables != null) put("numberOfTables", numberOfTables)
                    put("isGroupTournament", isGroupTournament)
                }
            )
            if (response.success == false) {
                TournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                TournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTournamentParticipants(
        clubId: String,
        tournamentId: String,
        classId: String? = null
    ): TournamentParticipantsResult {
        return try {
            val response = apiService.getTournamentParticipants(
                buildJsonObject {
                    put("clubId", clubId)
                    put("tournamentId", tournamentId)
                    if (!classId.isNullOrBlank()) put("classId", classId)
                }
            )
            TournamentParticipantsResult.Success(items = RepositoryMappers.mapTournamentParticipants(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentParticipantsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentParticipantsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addTournamentParticipant(
        clubId: String,
        tournamentId: String,
        memberId: String,
        classId: String? = null
    ): TournamentActionResult {
        return try {
            val response = apiService.addTournamentParticipant(
                buildJsonObject {
                    put("clubId", clubId)
                    put("tournamentId", tournamentId)
                    put("memberId", memberId)
                    if (!classId.isNullOrBlank()) put("classId", classId)
                }
            )
            if (response.success == false) {
                TournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                TournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun removeTournamentParticipant(
        clubId: String,
        tournamentId: String,
        participantId: String
    ): TournamentActionResult {
        return try {
            val response = apiService.removeTournamentParticipant(
                buildJsonObject {
                    put("clubId", clubId)
                    put("tournamentId", tournamentId)
                    put("participantId", participantId)
                }
            )
            if (response.success == false) {
                TournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                TournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTournamentMatches(clubId: String, tournamentId: String): TournamentMatchesResult {
        return try {
            val response = apiService.getTournamentMatches(clubId = clubId, tournamentId = tournamentId)
            TournamentMatchesResult.Success(items = RepositoryMappers.mapTournamentMatches(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentMatchesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentMatchesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun saveTournamentMatchResult(
        clubId: String,
        tournamentId: String,
        matchId: String,
        result: String
    ): TournamentActionResult {
        return try {
            val response = apiService.addTournamentMatchResult(
                buildJsonObject {
                    put("clubId", clubId)
                    put("tournamentId", tournamentId)
                    put("matchId", matchId)
                    put("result", result)
                }
            )
            if (response.success == false) {
                TournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                TournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadPermissionRoles(): PermissionRolesResult {
        return try {
            val response = apiService.getAvailableRoles()
            PermissionRolesResult.Success(items = RepositoryMappers.mapPermissionRoles(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PermissionRolesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PermissionRolesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadPermissionStructure(): PermissionStructureResult {
        return try {
            val response = apiService.getPermissionStructure()
            PermissionStructureResult.Success(items = RepositoryMappers.mapPermissionStructure(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PermissionStructureResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PermissionStructureResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadPermissionMembers(clubId: String, cacheBust: Long? = null): PermissionMembersResult {
        return try {
            val response = apiService.getPermissionMembers(clubId = clubId, cacheBust = cacheBust)
            PermissionMembersResult.Success(items = RepositoryMappers.mapPermissionMembers(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PermissionMembersResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PermissionMembersResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updatePermissionUserRole(clubId: String, userId: String, role: String): PermissionActionResult {
        return try {
            val response = apiService.updateUserRole(
                clubId = clubId,
                userId = userId,
                body = buildJsonObject { put("role", role) }
            )
            if (response.success == false) {
                PermissionActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                PermissionActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PermissionActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PermissionActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updatePermissionUserStatus(clubId: String, userId: String, approved: Boolean): PermissionActionResult {
        return try {
            val response = apiService.updateUserStatus(
                clubId = clubId,
                userId = userId,
                body = buildJsonObject { put("approved", approved) }
            )
            if (response.success == false) {
                PermissionActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                PermissionActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PermissionActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PermissionActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updatePermissionUserPermissions(
        clubId: String,
        userId: String,
        permissions: Map<String, Map<String, Boolean>>
    ): PermissionActionResult {
        return try {
            val response = apiService.updateUserPermissions(
                clubId = clubId,
                userId = userId,
                body = buildJsonObject {
                    put(
                        "permissions",
                        buildJsonObject {
                            permissions.forEach { (resource, actions) ->
                                put(
                                    resource,
                                    buildJsonObject {
                                        actions.forEach { (action, value) ->
                                            put(action, value)
                                        }
                                    }
                                )
                            }
                        }
                    )
                }
            )
            if (response.success == false) {
                PermissionActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                PermissionActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            PermissionActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            PermissionActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadClubTeams(clubId: String, seasonId: String? = null): ClubTeamsResult {
        return try {
            val response = apiService.getClubTeams(clubId = clubId, seasonId = seasonId)
            ClubTeamsResult.Success(items = RepositoryMappers.mapClubTeams(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubTeamsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubTeamsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadClubLeagues(clubId: String, seasonId: String? = null): ClubLeaguesResult {
        return try {
            val response = apiService.getClubTeamLeagues(clubId = clubId, seasonId = seasonId)
            ClubLeaguesResult.Success(items = RepositoryMappers.mapClubLeagues(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubLeaguesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubLeaguesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun createClubTeam(clubId: String, name: String, leagueId: String?, seasonId: String): ClubTeamActionResult {
        return try {
            val response = apiService.createClubTeam(
                clubId = clubId,
                body = buildJsonObject {
                    put("name", name)
                    if (!leagueId.isNullOrBlank()) put("leagueId", leagueId)
                    put("seasonId", seasonId)
                }
            )
            val obj = response as? JsonObject
            val id = obj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "id", "_id", "clubTeamId") }
            ClubTeamActionResult.Success(message = null, teamId = id)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubTeamActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubTeamActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateClubTeam(clubTeamId: String, name: String, leagueId: String?, seasonId: String): ClubTeamActionResult {
        return try {
            val response = apiService.updateClubTeam(
                clubTeamId = clubTeamId,
                body = buildJsonObject {
                    put("name", name)
                    put("leagueId", leagueId)
                    put("seasonId", seasonId)
                }
            )
            if (response.success == false) {
                ClubTeamActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubTeamActionResult.Success(message = response.message, teamId = clubTeamId)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubTeamActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubTeamActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteClubTeam(clubTeamId: String): ClubTeamActionResult {
        return try {
            val response = apiService.deleteClubTeam(clubTeamId = clubTeamId)
            if (response.success == false) {
                ClubTeamActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                ClubTeamActionResult.Success(message = response.message, teamId = clubTeamId)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            ClubTeamActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ClubTeamActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTeamDocuments(clubTeamId: String): TeamDocumentsResult {
        return try {
            val response = apiService.getTeamDocuments(clubTeamId = clubTeamId)
            TeamDocumentsResult.Success(items = RepositoryMappers.mapTeamDocuments(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TeamDocumentsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TeamDocumentsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun parseTeamDocument(documentId: String, leagueId: String): TeamDocumentParseResult {
        return try {
            val response = apiService.parseTeamDocument(documentId = documentId, leagueId = leagueId)
            TeamDocumentParseResult.Success(payload = response)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TeamDocumentParseResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TeamDocumentParseResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun uploadTeamDocument(
        clubTeamId: String,
        documentType: String,
        fileName: String,
        bytes: ByteArray
    ): TeamDocumentUploadResult {
        return try {
            val filePart = MultipartBody.Part.createFormData(
                "document",
                fileName,
                bytes.toRequestBody("application/octet-stream".toMediaType())
            )
            val docTypePart = documentType.toRequestBody("text/plain".toMediaType())
            val response = apiService.uploadTeamDocument(
                clubTeamId = clubTeamId,
                file = filePart,
                documentType = docTypePart
            )
            val obj = response as? JsonObject
            val id = obj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "id", "_id") }
            TeamDocumentUploadResult.Success(documentId = id, message = null)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TeamDocumentUploadResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TeamDocumentUploadResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadSchedulerJobs(clubId: String?): SchedulerJobsResult {
        return try {
            val response = apiService.getSchedulerExecutions(clubId = clubId)
            SchedulerJobsResult.Success(data = RepositoryMappers.mapSchedulerJobs(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            SchedulerJobsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            SchedulerJobsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTeamPlayerStats(clubId: String, leagueId: String, seasonId: String?): TeamPlayerStatsResult {
        return try {
            val response = apiService.getLeaguePlayerStats(clubId = clubId, leagueId = leagueId, seasonId = seasonId)
            TeamPlayerStatsResult.Success(items = RepositoryMappers.mapPlayerStats(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            TeamPlayerStatsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            TeamPlayerStatsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMyTischtennisAccount(): MyTischtennisAccountResult {
        return try {
            val response = apiService.getMyTischtennisAccount()
            MyTischtennisAccountResult.Success(
                account = RepositoryMappers.mapMyTischtennisAccount(response)
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisAccountResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisAccountResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMyTischtennisStatus(): MyTischtennisStatusResult {
        return try {
            val response = apiService.getMyTischtennisStatus()
            MyTischtennisStatusResult.Success(
                status = RepositoryMappers.mapMyTischtennisStatus(response)
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisStatusResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisStatusResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun verifyMyTischtennis(password: String?): MyTischtennisActionResult {
        return try {
            val response = apiService.verifyMyTischtennis(
                buildJsonObject {
                    if (!password.isNullOrBlank()) put("password", password)
                }
            ) as? JsonObject
            val isSuccess = response?.string("success")?.equals("true", ignoreCase = true)
            if (isSuccess == false) {
                MyTischtennisActionResult.Error(
                    code = response.string("code"),
                    message = response.string("error") ?: response.string("message")
                )
            } else {
                MyTischtennisActionResult.Success(message = response?.string("message"), payload = response)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun saveMyTischtennisAccount(email: String, password: String?): MyTischtennisActionResult {
        return runMyTischtennisAction {
            apiService.upsertMyTischtennisAccount(
                buildJsonObject {
                    put("email", email)
                    if (!password.isNullOrBlank()) put("password", password)
                }
            )
        }
    }

    suspend fun deleteMyTischtennisAccountLink(): MyTischtennisActionResult {
        return runMyTischtennisAction {
            apiService.deleteMyTischtennisAccount()
        }
    }

    suspend fun loadLogs(
        limit: Int,
        offset: Int,
        backend: String?,
        logType: String?,
        method: String?,
        statusCode: String?,
        path: String?,
        startDate: String?,
        endDate: String?
    ): LogsResult {
        return try {
            val params = linkedMapOf(
                "limit" to limit.toString(),
                "offset" to offset.toString()
            )
            val normalizedBackend = backend?.trim().orEmpty()
            val normalizedPath = path?.trim().orEmpty()
            when (normalizedBackend) {
                "mytischtennis" -> params["path"] = "/mytischtennis"
                "own" -> params["path"] = "NOT:/mytischtennis"
                else -> if (normalizedPath.isNotBlank()) params["path"] = normalizedPath
            }

            if (!logType.isNullOrBlank()) params["logType"] = logType.trim()
            if (!method.isNullOrBlank()) params["method"] = method.trim()
            if (!statusCode.isNullOrBlank()) params["statusCode"] = statusCode.trim()
            if (!startDate.isNullOrBlank()) params["startDate"] = startDate.trim()
            if (!endDate.isNullOrBlank()) params["endDate"] = endDate.trim()

            val response = apiService.getLogs(params)
            LogsResult.Success(data = RepositoryMappers.mapLogsPage(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            LogsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            LogsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadLogDetail(id: String): LogDetailResult {
        return try {
            val response = apiService.getLogDetail(id = id)
            val detail = RepositoryMappers.mapLogDetail(response)
                ?: return LogDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            LogDetailResult.Success(item = detail)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            LogDetailResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            LogDetailResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun parseMyTischtennisUrl(url: String): MyTischtennisActionResult {
        return try {
            val response = apiService.parseMyTischtennisUrl(
                buildJsonObject { put("url", url) }
            ) as? JsonObject
            val success = response?.string("success")?.equals("true", ignoreCase = true) ?: false
            if (!success) {
                MyTischtennisActionResult.Error(
                    code = response?.string("code"),
                    message = response?.string("error") ?: response?.string("message") ?: AppErrorUtils.unknown()
                )
            } else {
                MyTischtennisActionResult.Success(message = response?.string("message"), payload = response)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun configureMyTischtennisTeam(url: String, clubTeamId: String): MyTischtennisActionResult {
        return runMyTischtennisAction {
            apiService.configureMyTischtennisTeam(
                buildJsonObject {
                    put("url", url)
                    put("clubTeamId", clubTeamId)
                    put("createLeague", true)
                    put("createSeason", true)
                }
            )
        }
    }

    suspend fun configureMyTischtennisLeague(url: String): MyTischtennisActionResult {
        return runMyTischtennisAction {
            apiService.configureMyTischtennisLeague(
                buildJsonObject {
                    put("url", url)
                    put("createSeason", true)
                }
            )
        }
    }

    suspend fun startMyTischtennisFetchJob(clubTeamId: String): MyTischtennisActionResult {
        return try {
            val response = apiService.startMyTischtennisFetchJob(
                buildJsonObject { put("clubTeamId", clubTeamId) }
            ) as? JsonObject
            val jobId = response?.string("jobId")
            if (jobId.isNullOrBlank()) {
                MyTischtennisActionResult.Error(code = null, message = response?.string("message") ?: AppErrorUtils.unknown())
            } else {
                MyTischtennisActionResult.Success(
                    message = response.string("message"),
                    payload = response
                )
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun getMyTischtennisFetchJob(jobId: String): MyTischtennisActionResult {
        return try {
            val response = apiService.getMyTischtennisFetchJob(jobId = jobId) as? JsonObject
            MyTischtennisActionResult.Success(message = null, payload = response)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadOfficialTournaments(clubId: String): OfficialTournamentsResult {
        return try {
            val response = apiService.getOfficialTournaments(clubId = clubId)
            OfficialTournamentsResult.Success(items = RepositoryMappers.mapOfficialTournaments(response))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadOfficialTournamentSummary(clubId: String): OfficialTournamentSummaryResult {
        return try {
            val response = apiService.getOfficialTournamentSummary(clubId = clubId)
            OfficialTournamentSummaryResult.Success(
                data = RepositoryMappers.mapOfficialTournamentSummary(response)
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentSummaryResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentSummaryResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun uploadOfficialTournamentPdf(
        clubId: String,
        fileName: String,
        bytes: ByteArray
    ): OfficialTournamentUploadResult {
        return try {
            val filePart = MultipartBody.Part.createFormData(
                "pdf",
                fileName,
                bytes.toRequestBody("application/pdf".toMediaType())
            )
            val response = apiService.uploadOfficialTournamentPdf(
                clubId = clubId,
                pdf = filePart
            ) as? JsonObject
            OfficialTournamentUploadResult.Success(
                tournamentId = response?.string("id")
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentUploadResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentUploadResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadOfficialTournamentDetail(clubId: String, id: String): OfficialTournamentDetailResult {
        return try {
            val response = apiService.getOfficialTournament(clubId = clubId, id = id)
            val detail = RepositoryMappers.mapOfficialTournamentDetail(response)
                ?: return OfficialTournamentDetailResult.Error(code = null, message = AppErrorUtils.unknown())
            OfficialTournamentDetailResult.Success(data = detail)
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentDetailResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentDetailResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun upsertOfficialParticipation(
        clubId: String,
        tournamentId: String,
        competitionId: Int,
        memberId: String,
        wants: Boolean,
        registered: Boolean,
        participated: Boolean,
        placement: String?
    ): OfficialTournamentActionResult {
        return try {
            val response = apiService.upsertOfficialParticipation(
                clubId = clubId,
                id = tournamentId,
                body = buildJsonObject {
                    put("competitionId", competitionId)
                    put("memberId", memberId)
                    put("wants", wants)
                    put("registered", registered)
                    put("participated", participated)
                    put("placement", placement)
                }
            )
            if (response.success == false) {
                OfficialTournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                OfficialTournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateOfficialParticipationStatus(
        clubId: String,
        tournamentId: String,
        competitionId: Int,
        memberId: String,
        action: String
    ): OfficialTournamentActionResult {
        return try {
            val response = apiService.updateOfficialStatus(
                clubId = clubId,
                id = tournamentId,
                body = buildJsonObject {
                    put("competitionId", competitionId)
                    put("memberId", memberId)
                    put("action", action)
                }
            )
            if (response.success == false) {
                OfficialTournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                OfficialTournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteOfficialTournament(clubId: String, tournamentId: String): OfficialTournamentActionResult {
        return try {
            val response = apiService.deleteOfficialTournament(clubId = clubId, id = tournamentId)
            if (response.success == false) {
                OfficialTournamentActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                OfficialTournamentActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            OfficialTournamentActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            OfficialTournamentActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun updateMemberRatings(clubId: String): MemberActionResult {
        return try {
            val response = apiService.updateRatings(clubId = clubId)
            if (response.success == false) {
                MemberActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                MemberActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun saveMember(
        clubId: String,
        memberId: String?,
        firstName: String,
        lastName: String,
        active: Boolean,
        testMembership: Boolean,
        contacts: List<MemberContactItem>
    ): MemberSaveResult {
        return try {
            val response = apiService.setClubMembers(
                clubId = clubId,
                body = buildJsonObject {
                    put("id", memberId)
                    put("firstname", firstName)
                    put("lastname", lastName)
                    put("active", active)
                    put("testMembership", testMembership)
                    put(
                        "contacts",
                        buildJsonArray {
                            contacts.forEach { contact ->
                                add(
                                    buildJsonObject {
                                        put("type", contact.type)
                                        put("value", contact.value)
                                    }
                                )
                            }
                        }
                    )
                }
            )
            val responseObj = response as? kotlinx.serialization.json.JsonObject
            val code = responseObj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "code") }
            val error = responseObj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "error") }
            val message = responseObj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "message") }
            if (!error.isNullOrBlank()) {
                MemberSaveResult.Error(code = code, message = error)
            } else {
                MemberSaveResult.Success(message = message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberSaveResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberSaveResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMemberImages(clubId: String, memberId: String): MemberImagesResult {
        return try {
            val gallery = apiService.getClubMemberGallery(clubId = clubId, format = "json")
            MemberImagesResult.Success(
                images = RepositoryMappers.mapMemberGalleryImages(gallery, memberId = memberId)
            )
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberImagesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberImagesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun uploadMemberImage(
        clubId: String,
        memberId: String,
        fileName: String,
        bytes: ByteArray
    ): MemberActionResult {
        return runQuickMemberAction {
            val requestBody = bytes.toRequestBody("image/*".toMediaType())
            val part = MultipartBody.Part.createFormData("image", fileName, requestBody)
            apiService.uploadClubMemberImage(clubId = clubId, memberId = memberId, image = part)
        }
    }

    suspend fun deleteMemberImage(
        clubId: String,
        memberId: String,
        imageId: String
    ): MemberActionResult {
        return runQuickMemberAction {
            apiService.deleteClubMemberImage(clubId = clubId, memberId = memberId, imageId = imageId)
        }
    }

    suspend fun setPrimaryMemberImage(
        clubId: String,
        memberId: String,
        imageId: String
    ): MemberActionResult {
        return runQuickMemberAction {
            apiService.setClubMemberPrimaryImage(clubId = clubId, memberId = memberId, imageId = imageId)
        }
    }

    suspend fun loadMemberNotes(clubId: String, memberId: String): MemberNotesResult {
        return try {
            val notes = apiService.getMemberNotes(memberId = memberId, clubId = clubId)
            MemberNotesResult.Success(notes = RepositoryMappers.mapMemberNotes(notes))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberNotesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberNotesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addMemberNote(clubId: String, memberId: String, content: String): MemberNotesResult {
        return try {
            val notes = apiService.addMemberNote(
                buildJsonObject {
                    put("clubId", clubId)
                    put("memberId", memberId)
                    put("content", content)
                }
            )
            MemberNotesResult.Success(notes = RepositoryMappers.mapMemberNotes(notes))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberNotesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberNotesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteMemberNote(clubId: String, noteId: String): MemberNotesResult {
        return try {
            val notes = apiService.deleteMemberNote(
                noteId = noteId,
                body = buildJsonObject { put("clubId", clubId) }
            )
            MemberNotesResult.Success(notes = RepositoryMappers.mapMemberNotes(notes))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberNotesResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberNotesResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMemberTransferConfig(clubId: String): MemberTransferConfigResult {
        return try {
            val response = apiService.getMemberTransferConfig(clubId = clubId) as? JsonObject
                ?: return MemberTransferConfigResult.Success(config = null)
            val success = response.string("success")?.equals("true", ignoreCase = true) ?: false
            if (!success) {
                MemberTransferConfigResult.Error(
                    message = response.string("error")
                        ?: response.string("message")
                        ?: AppErrorUtils.unknown()
                )
            } else {
                val configObj = response["config"] as? JsonObject
                MemberTransferConfigResult.Success(config = configObj?.let(RepositoryMappers::mapMemberTransferConfig))
            }
        } catch (e: HttpException) {
            if (e.code() == 404) return MemberTransferConfigResult.Success(config = null)
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberTransferConfigResult.Error(
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberTransferConfigResult.Error(message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun saveMemberTransferConfig(clubId: String, input: MemberTransferConfigInput): MemberTransferActionResult {
        return try {
            val payload = buildJsonObject {
                put("server", input.server)
                if (input.loginEndpoint != null) put("loginEndpoint", input.loginEndpoint)
                put("loginFormat", input.loginFormat)
                if (!input.loginCredentials.isNullOrEmpty()) {
                    put(
                        "loginCredentials",
                        buildJsonObject {
                            input.loginCredentials.forEach { (key, value) ->
                                if (key.isNotBlank() && value.isNotBlank()) put(key, value)
                            }
                        }
                    )
                }
                put("transferEndpoint", input.transferEndpoint)
                put("transferMethod", input.transferMethod)
                put("transferFormat", input.transferFormat)
                put("transferTemplate", input.transferTemplate)
                put("useBulkMode", input.useBulkMode)
                if (input.bulkWrapperTemplate != null) put("bulkWrapperTemplate", input.bulkWrapperTemplate)
            }
            val response = apiService.saveMemberTransferConfig(clubId = clubId, body = payload) as? JsonObject
                ?: return MemberTransferActionResult.Error(AppErrorUtils.unknown())
            val success = response.string("success")?.equals("true", ignoreCase = true) ?: false
            if (!success) {
                MemberTransferActionResult.Error(
                    response.string("error") ?: response.string("message") ?: AppErrorUtils.unknown()
                )
            } else {
                val configObj = response["config"] as? JsonObject
                val configId = configObj?.string("id")
                MemberTransferActionResult.Success(
                    message = response.string("message"),
                    configId = configId
                )
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberTransferActionResult.Error(AppErrorUtils.backendOrThrowable(parsed?.message, e))
        } catch (e: Exception) {
            MemberTransferActionResult.Error(AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun deleteMemberTransferConfig(clubId: String): MemberTransferActionResult {
        return try {
            val response = apiService.deleteMemberTransferConfig(clubId = clubId) as? JsonObject
                ?: return MemberTransferActionResult.Error(AppErrorUtils.unknown())
            val success = response.string("success")?.equals("true", ignoreCase = true) ?: false
            if (!success) {
                MemberTransferActionResult.Error(
                    response.string("error") ?: response.string("message") ?: AppErrorUtils.unknown()
                )
            } else {
                MemberTransferActionResult.Success(message = response.string("message"), configId = null)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberTransferActionResult.Error(AppErrorUtils.backendOrThrowable(parsed?.message, e))
        } catch (e: Exception) {
            MemberTransferActionResult.Error(AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun executeMemberTransfer(clubId: String, input: MemberTransferConfigInput): MemberTransferExecutionResult {
        return try {
            val payload = buildJsonObject {
                if (input.loginEndpoint != null) put("loginEndpoint", input.loginEndpoint)
                put("loginFormat", input.loginFormat)
                if (!input.loginCredentials.isNullOrEmpty()) {
                    put(
                        "loginCredentials",
                        buildJsonObject {
                            input.loginCredentials.forEach { (key, value) ->
                                if (key.isNotBlank() && value.isNotBlank()) put(key, value)
                            }
                        }
                    )
                }
                put("transferEndpoint", input.transferEndpoint)
                put("transferMethod", input.transferMethod)
                put("transferFormat", input.transferFormat)
                put("transferTemplate", input.transferTemplate)
                put("useBulkMode", input.useBulkMode)
                if (input.bulkWrapperTemplate != null) put("bulkWrapperTemplate", input.bulkWrapperTemplate)
            }
            val response = apiService.transferClubMembers(clubId = clubId, body = payload) as? JsonObject
                ?: return MemberTransferExecutionResult.Error(AppErrorUtils.unknown())
            val success = response.string("success")?.equals("true", ignoreCase = true) ?: false
            val summary = RepositoryMappers.mapMemberTransferSummary(response)
            if (success) {
                MemberTransferExecutionResult.Success(summary)
            } else {
                MemberTransferExecutionResult.Error(
                    message = summary.message ?: response.string("error") ?: AppErrorUtils.unknown(),
                    summary = summary
                )
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberTransferExecutionResult.Error(AppErrorUtils.backendOrThrowable(parsed?.message, e))
        } catch (e: Exception) {
            MemberTransferExecutionResult.Error(AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadTrainingGroups(clubId: String): MemberTrainingGroupsResult {
        return try {
            val groups = apiService.getTrainingGroups(clubId = clubId)
            MemberTrainingGroupsResult.Success(groups = RepositoryMappers.mapTrainingGroups(groups))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberTrainingGroupsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberTrainingGroupsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun loadMemberTrainingGroups(clubId: String, memberId: String): MemberTrainingGroupsResult {
        return try {
            val groups = apiService.getMemberTrainingGroups(clubId = clubId, memberId = memberId)
            MemberTrainingGroupsResult.Success(groups = RepositoryMappers.mapTrainingGroups(groups))
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberTrainingGroupsResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberTrainingGroupsResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun addMemberToTrainingGroup(
        clubId: String,
        memberId: String,
        groupId: String
    ): MemberActionResult {
        return try {
            val response = apiService.addMemberToTrainingGroup(
                clubId = clubId,
                groupId = groupId,
                memberId = memberId
            )
            if (response.success == false) {
                MemberActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                MemberActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun removeMemberFromTrainingGroup(
        clubId: String,
        memberId: String,
        groupId: String
    ): MemberActionResult {
        return try {
            val response = apiService.removeMemberFromTrainingGroup(
                clubId = clubId,
                groupId = groupId,
                memberId = memberId
            )
            if (response.success == false) {
                MemberActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                MemberActionResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun quickRemoveTestMembership(clubId: String, memberId: String): MemberActionResult {
        return runQuickMemberAction {
            apiService.quickUpdateTestMembership(clubId = clubId, memberId = memberId)
        }
    }

    suspend fun quickDeactivateMember(clubId: String, memberId: String): MemberActionResult {
        return runQuickMemberAction {
            apiService.quickDeactivateMember(clubId = clubId, memberId = memberId)
        }
    }

    private suspend fun runQuickMemberAction(call: suspend () -> JsonElement): MemberActionResult {
        return try {
            val response = call()
            val obj = response as? JsonObject
            val success = obj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "success") }
                ?.equals("true", ignoreCase = true)
                ?: true
            val code = obj?.let { de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "code") }
            val message = obj?.let {
                de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "message", "error")
            }
            if (success) {
                MemberActionResult.Success(message)
            } else {
                MemberActionResult.Error(code = code, message = message)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MemberActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MemberActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    private suspend fun runMyTischtennisAction(call: suspend () -> BaseResponse<JsonElement>): MyTischtennisActionResult {
        return try {
            val response = call()
            if (response.success == false) {
                MyTischtennisActionResult.Error(code = response.code, message = response.error ?: response.message)
            } else {
                MyTischtennisActionResult.Success(message = response.message, payload = null)
            }
        } catch (e: HttpException) {
            val parsed = e.response()?.errorBody()?.string()?.let(RepositoryMappers::parseErrorPayload)
            MyTischtennisActionResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            MyTischtennisActionResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun login(email: String, password: String): LoginResult {
        return try {
            val response = apiService.login(
                de.trainingstagebuch.app.network.LoginRequest(
                    email = email,
                    password = password
                )
            )
            val token = response["token"]?.jsonPrimitive?.contentOrNull
            if (token.isNullOrBlank()) {
                val code = response["code"]?.jsonPrimitive?.contentOrNull
                val message = response["error"]?.jsonPrimitive?.contentOrNull
                    ?: response["message"]?.jsonPrimitive?.contentOrNull
                LoginResult.Error(code = code, message = message)
            } else {
                LoginResult.Success(token = token)
            }
        } catch (e: HttpException) {
            val rawError = e.response()?.errorBody()?.string()
            val parsed = rawError?.let(RepositoryMappers::parseErrorPayload)
            LoginResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            LoginResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun register(email: String, password: String): RegisterResult {
        return try {
            val response = apiService.register(RegisterRequest(email = email, password = password))
            if (response.success == false) {
                RegisterResult.Error(
                    code = response.code,
                    message = response.error ?: response.message
                )
            } else {
                RegisterResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val rawError = e.response()?.errorBody()?.string()
            val parsed = rawError?.let(RepositoryMappers::parseErrorPayload)
            RegisterResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            RegisterResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun activate(activationCode: String): ActivateResult {
        return try {
            val response = apiService.activate(activationCode)
            if (response.success == false) {
                ActivateResult.Error(
                    code = response.code,
                    message = response.error ?: response.message
                )
            } else {
                ActivateResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val rawError = e.response()?.errorBody()?.string()
            val parsed = rawError?.let(RepositoryMappers::parseErrorPayload)
            ActivateResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ActivateResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun forgotPassword(email: String): ForgotPasswordResult {
        return try {
            val response = apiService.forgotPassword(
                buildJsonObject { put("email", email) }
            )
            if (response.success == false) {
                ForgotPasswordResult.Error(
                    code = response.code,
                    message = response.error ?: response.message
                )
            } else {
                ForgotPasswordResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val rawError = e.response()?.errorBody()?.string()
            val parsed = rawError?.let(RepositoryMappers::parseErrorPayload)
            ForgotPasswordResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ForgotPasswordResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    suspend fun resetPassword(token: String, password: String): ResetPasswordResult {
        return try {
            val response = apiService.resetPassword(
                buildJsonObject {
                    put("token", token)
                    put("password", password)
                }
            )
            if (response.success == false) {
                ResetPasswordResult.Error(
                    code = response.code,
                    message = response.error ?: response.message
                )
            } else {
                ResetPasswordResult.Success(message = response.message)
            }
        } catch (e: HttpException) {
            val rawError = e.response()?.errorBody()?.string()
            val parsed = rawError?.let(RepositoryMappers::parseErrorPayload)
            ResetPasswordResult.Error(
                code = parsed?.code,
                message = AppErrorUtils.backendOrThrowable(parsed?.message, e)
            )
        } catch (e: Exception) {
            ResetPasswordResult.Error(code = null, message = AppErrorUtils.fromThrowable(e))
        }
    }

    fun disconnectSocketOnLogout() {
        SocketManager.requestDisconnect()
    }

    fun connectSocketOnLogin() {
        SocketManager.requestConnect()
    }

    private fun extractCreatedClubId(response: JsonElement): String? {
        val obj = response as? JsonObject
        if (obj == null) {
            return response.jsonPrimitive.contentOrNull?.trim()?.ifBlank { null }
        }

        val dataElement = obj["data"]
        val fromDataElement = dataElement?.jsonPrimitive?.contentOrNull?.trim()?.ifBlank { null }
        if (!fromDataElement.isNullOrBlank()) return fromDataElement

        val dataObject = dataElement as? JsonObject
        val fromDataObject = dataObject?.let {
            de.trainingstagebuch.app.utils.JsonSafeUtils.getString(it, "id", "clubId")
        }?.trim()?.ifBlank { null }
        if (!fromDataObject.isNullOrBlank()) return fromDataObject

        return de.trainingstagebuch.app.utils.JsonSafeUtils.getString(obj, "id", "clubId")
            ?.trim()
            ?.ifBlank { null }
    }

    private fun JsonObject.string(key: String): String? {
        return de.trainingstagebuch.app.utils.JsonSafeUtils.getString(this, key)
    }

}

sealed interface LoginResult {
    data class Success(val token: String) : LoginResult
    data class Error(val code: String?, val message: String?) : LoginResult
}

sealed interface RegisterResult {
    data class Success(val message: String?) : RegisterResult
    data class Error(val code: String?, val message: String?) : RegisterResult
}

sealed interface HomeResult {
    data class Success(val data: HomeData) : HomeResult
    data class Error(val message: String) : HomeResult
}

sealed interface CreateClubResult {
    data class Success(val createdClubId: String?) : CreateClubResult
    data class Error(val code: String?, val message: String?) : CreateClubResult
}

sealed interface ClubResult {
    data class Success(val data: ClubDetails) : ClubResult
    data class AccessDenied(val requested: Boolean, val message: String?) : ClubResult
    data class Error(val code: String? = null, val message: String) : ClubResult
}

sealed interface ClubAccessRequestResult {
    data class Success(val message: String?) : ClubAccessRequestResult
    data class AlreadyRequested(val message: String?) : ClubAccessRequestResult
    data class Error(val code: String?, val message: String?) : ClubAccessRequestResult
}

sealed interface ClubSettingsResult {
    data class Success(val settings: ClubSettingsData) : ClubSettingsResult
    data class Error(val code: String? = null, val message: String) : ClubSettingsResult
}

sealed interface ClubSettingsActionResult {
    data class Success(val message: String?) : ClubSettingsActionResult
    data class Error(val code: String?, val message: String?) : ClubSettingsActionResult
}

sealed interface PendingApprovalsResult {
    data class Success(val users: List<PendingApprovalUser>) : PendingApprovalsResult
    data class Error(val code: String?, val message: String?) : PendingApprovalsResult
}

sealed interface ClubTrainingGroupsResult {
    data class Success(val groups: List<ClubTrainingGroup>) : ClubTrainingGroupsResult
    data class Error(val code: String?, val message: String?) : ClubTrainingGroupsResult
}

sealed interface ClubTrainingTimesResult {
    data class Success(val groups: List<ClubTrainingTimeGroup>) : ClubTrainingTimesResult
    data class Error(val code: String?, val message: String?) : ClubTrainingTimesResult
}

sealed interface ClubActionResult {
    data class Success(val message: String?) : ClubActionResult
    data class Error(val code: String?, val message: String?) : ClubActionResult
}

sealed interface ActivateResult {
    data class Success(val message: String?) : ActivateResult
    data class Error(val code: String?, val message: String?) : ActivateResult
}

sealed interface ForgotPasswordResult {
    data class Success(val message: String?) : ForgotPasswordResult
    data class Error(val code: String?, val message: String?) : ForgotPasswordResult
}

sealed interface ResetPasswordResult {
    data class Success(val message: String?) : ResetPasswordResult
    data class Error(val code: String?, val message: String?) : ResetPasswordResult
}

data class HomeData(
    val clubCount: Int,
    val clubNames: List<String>,
    val clubs: List<HomeClub> = emptyList()
)

data class HomeClub(
    val id: String,
    val name: String
)

data class ClubDetails(
    val id: String?,
    val name: String,
    val members: List<MemberItem>
)

data class ClubSettingsData(
    val greetingText: String,
    val associationMemberNumber: String
)

data class ClubTrainingGroup(
    val id: String,
    val name: String
)

data class ClubTrainingTimeGroup(
    val id: String,
    val name: String,
    val trainingTimes: List<ClubTrainingTime>
)

data class ClubTrainingTime(
    val id: String,
    val weekday: Int,
    val startTime: String,
    val endTime: String
)

data class PendingApprovalUser(
    val id: String,
    val firstName: String,
    val lastName: String,
    val email: String?
)

data class MemberItem(
    val id: String,
    val firstName: String,
    val lastName: String,
    val displayName: String,
    val active: Boolean,
    val testMembership: Boolean,
    val contacts: List<MemberContactItem> = emptyList()
)

data class MemberImageItem(
    val imageId: String,
    val memberId: String,
    val url: String?,
    val isPrimary: Boolean
)

data class MemberContactItem(
    val type: String,
    val value: String
)

data class TrainingGroupItem(
    val id: String,
    val name: String
)

data class DiaryDateEntry(
    val id: String,
    val date: String,
    val trainingStart: String?,
    val trainingEnd: String?,
    val tags: List<DiaryTagItem> = emptyList()
)

data class DiaryParticipant(
    val id: String,
    val memberId: String,
    val groupId: String?
)

data class DiaryActivityItem(
    val id: String,
    val description: String
)

data class DiaryTagItem(
    val id: String,
    val name: String
)

data class DiaryPlanItem(
    val id: String,
    val activity: String,
    val duration: String?,
    val durationText: String?,
    val isTimeblock: Boolean,
    val groupId: String? = null,
    val orderId: Int? = null,
    val predefinedActivityId: String? = null
)

data class DiaryGroupItem(
    val id: String,
    val name: String,
    val lead: String
)

data class MemberNoteItem(
    val id: String,
    val content: String,
    val createdAt: String?
)

data class DiaryAccidentItem(
    val id: String,
    val accident: String,
    val happenedAt: String?
)

data class MemberActivityStatItem(
    val activity: String,
    val count: Int
)

data class MemberParticipationItem(
    val date: String,
    val activity: String
)

data class PredefinedActivityItem(
    val id: String,
    val name: String,
    val code: String?,
    val duration: String?,
    val durationText: String?,
    val description: String? = null,
    val imageLink: String? = null,
    val drawingData: String? = null,
    val images: List<PredefinedActivityImage> = emptyList()
)

data class PredefinedActivityImage(
    val imageId: String,
    val url: String?,
    val drawingData: String?
)

data class PredefinedActivityInput(
    val name: String,
    val code: String?,
    val duration: String?,
    val durationText: String?,
    val description: String?,
    val imageLink: String?,
    val drawingData: String?
)

data class TrainingStatsData(
    val members: List<TrainingStatsMember>,
    val trainingsCount12Months: Int,
    val trainingsCount3Months: Int,
    val trainingDays: List<TrainingDayStatsItem>
)

data class TrainingStatsMember(
    val id: String,
    val firstName: String,
    val lastName: String,
    val ttr: Int?,
    val qttr: Int?,
    val birthDate: String?,
    val participation12Months: Int,
    val participation3Months: Int,
    val participationTotal: Int,
    val lastTraining: String?
)

data class TrainingDayStatsItem(
    val id: String,
    val date: String,
    val participantCount: Int
)

data class ScheduleTeamItem(
    val id: String,
    val name: String,
    val leagueId: String?,
    val leagueName: String?
)

data class ScheduleMatchItem(
    val id: String,
    val date: String?,
    val time: String?,
    val homeTeamName: String?,
    val guestTeamName: String?,
    val leagueName: String?,
    val homeMatchPoints: Int?,
    val guestMatchPoints: Int?,
    val isCompleted: Boolean,
    val code: String?,
    val homePin: String?,
    val guestPin: String?,
    val locationName: String?,
    val locationAddress: String?,
    val locationZip: String?,
    val locationCity: String?,
    val playersReady: List<String>,
    val playersPlanned: List<String>,
    val playersPlayed: List<String>
)

data class ScheduleLeagueTableRow(
    val teamId: String,
    val teamName: String,
    val matchPoints: String,
    val setsWon: String,
    val setsLost: String,
    val tablePoints: String,
    val pointRatio: String
)

data class TournamentItem(
    val id: String,
    val name: String,
    val date: String?,
    val winningSets: Int,
    val numberOfTables: Int?,
    val isGroupTournament: Boolean,
    val type: String?,
    val location: String?
)

data class TournamentParticipantItem(
    val id: String,
    val memberId: String?,
    val name: String,
    val seeded: Boolean,
    val gaveUp: Boolean,
    val classId: String?,
    val isExternal: Boolean
)

data class TournamentMatchItem(
    val id: String,
    val round: String,
    val groupNumber: Int?,
    val classId: String?,
    val player1Name: String?,
    val player2Name: String?,
    val result: String?,
    val isFinished: Boolean,
    val isActive: Boolean,
    val tableNumber: Int?
)

data class PermissionRoleItem(
    val value: String,
    val label: String,
    val description: String?
)

data class PermissionResourceItem(
    val label: String,
    val actions: List<String>
)

data class PermissionMemberItem(
    val userId: String,
    val role: String,
    val approved: Boolean,
    val isOwner: Boolean,
    val email: String?,
    val firstName: String?,
    val lastName: String?,
    val permissions: Map<String, Map<String, Boolean>>,
    val effectivePermissions: Map<String, Map<String, Boolean>>
)

data class ClubTeamItem(
    val id: String,
    val name: String,
    val leagueId: String?,
    val leagueName: String?,
    val seasonId: String?,
    val seasonName: String?,
    val myTischtennisTeamId: String?,
    val leagueAssociation: String?,
    val leagueGroupName: String?,
    val leagueGroupId: String?,
    val createdAt: String?
)

data class ClubLeagueItem(
    val id: String,
    val name: String,
    val seasonId: String?
)

data class TeamDocumentItem(
    val id: String,
    val clubTeamId: String,
    val documentType: String,
    val fileName: String?,
    val mimeType: String?,
    val size: Long?,
    val createdAt: String?
)

data class SchedulerJobsOverview(
    val ratingUpdates: SchedulerJobInfo? = null,
    val matchResults: SchedulerJobInfo? = null
)

data class SchedulerJobInfo(
    val lastRun: String?,
    val success: Boolean?,
    val updatedCount: Int?,
    val fetchedCount: Int?,
    val teamDetails: List<TeamJobDetail>
)

data class TeamJobDetail(
    val clubTeamId: String,
    val teamName: String?,
    val success: Boolean,
    val lastRun: String?
)

data class TeamPlayerStatItem(
    val memberId: String,
    val firstName: String,
    val lastName: String,
    val totalSeason: Int,
    val totalFirstHalf: Int,
    val totalSecondHalf: Int
)

data class OfficialTournamentItem(
    val id: String,
    val name: String,
    val date: String?,
    val location: String?,
    val status: String?
)

data class OfficialTournamentSummary(
    val total: Int,
    val plannedParticipations: Int
)

data class OfficialTournamentDetailData(
    val id: String,
    val title: String?,
    val termin: String?,
    val competitions: List<OfficialCompetitionItem>,
    val participation: List<OfficialParticipationItem>
)

data class OfficialCompetitionItem(
    val id: Int,
    val name: String,
    val startTime: String?,
    val entryFee: String?
)

data class OfficialParticipationItem(
    val competitionId: Int,
    val memberId: String,
    val wants: Boolean,
    val registered: Boolean,
    val participated: Boolean,
    val placement: String?
)

data class MyTischtennisAccountData(
    val email: String,
    val clubId: String?,
    val clubName: String?,
    val fedNickname: String?,
    val lastLoginSuccess: String?,
    val lastLoginAttempt: String?
)

data class MyTischtennisStatusData(
    val hasPassword: Boolean,
    val configured: Boolean
)

data class LogItem(
    val id: String,
    val createdAt: String?,
    val logType: String,
    val method: String,
    val path: String,
    val statusCode: Int?,
    val executionTime: Long?,
    val errorMessage: String?
)

data class LogDetailItem(
    val id: String,
    val createdAt: String?,
    val logType: String,
    val method: String,
    val path: String,
    val statusCode: Int?,
    val executionTime: Long?,
    val errorMessage: String?,
    val ipAddress: String?,
    val schedulerJobType: String?,
    val requestBody: String?,
    val responseBody: String?
)

data class LogsPageData(
    val logs: List<LogItem> = emptyList(),
    val total: Int = 0
)

data class MemberTransferConfig(
    val id: String?,
    val server: String,
    val loginEndpoint: String?,
    val loginFormat: String,
    val loginUsername: String?,
    val loginPassword: String?,
    val loginAdditionalField1: String?,
    val loginAdditionalField2: String?,
    val transferEndpoint: String,
    val transferMethod: String,
    val transferFormat: String,
    val transferTemplate: String,
    val useBulkMode: Boolean,
    val bulkWrapperTemplate: String?
)

data class MemberTransferConfigInput(
    val server: String,
    val loginEndpoint: String?,
    val loginFormat: String,
    val loginCredentials: Map<String, String>?,
    val transferEndpoint: String,
    val transferMethod: String,
    val transferFormat: String,
    val transferTemplate: String,
    val useBulkMode: Boolean,
    val bulkWrapperTemplate: String?
)

data class MemberTransferSummary(
    val success: Boolean,
    val message: String?,
    val transferred: Int,
    val total: Int,
    val invalidMembers: List<String>,
    val errors: List<String>
)

sealed interface MembersResult {
    data class Success(val members: List<MemberItem>) : MembersResult
    data class Error(val message: String) : MembersResult
}

sealed interface DiaryDatesResult {
    data class Success(val dates: List<DiaryDateEntry>) : DiaryDatesResult
    data class Error(val code: String?, val message: String?) : DiaryDatesResult
}

sealed interface DiaryCreateDateResult {
    data class Success(val entry: DiaryDateEntry) : DiaryCreateDateResult
    data class Error(val code: String?, val message: String?) : DiaryCreateDateResult
}

sealed interface DiaryActionResult {
    data class Success(val message: String?) : DiaryActionResult
    data class Error(val code: String?, val message: String?) : DiaryActionResult
}

sealed interface DiaryParticipantsResult {
    data class Success(val participants: List<DiaryParticipant>) : DiaryParticipantsResult
    data class Error(val code: String?, val message: String?) : DiaryParticipantsResult
}

sealed interface DiaryParticipantActionResult {
    data class Success(val participant: DiaryParticipant?) : DiaryParticipantActionResult
    data class Error(val code: String?, val message: String?) : DiaryParticipantActionResult
}

sealed interface DiaryActivitiesResult {
    data class Success(val activities: List<DiaryActivityItem>) : DiaryActivitiesResult
    data class Error(val code: String?, val message: String?) : DiaryActivitiesResult
}

sealed interface DiaryAddActivityResult {
    data class Success(val activity: DiaryActivityItem) : DiaryAddActivityResult
    data class Error(val code: String?, val message: String?) : DiaryAddActivityResult
}

sealed interface DiaryTagsResult {
    data class Success(val tags: List<DiaryTagItem>) : DiaryTagsResult
    data class Error(val code: String?, val message: String?) : DiaryTagsResult
}

sealed interface DiaryCreateTagResult {
    data class Success(val tag: DiaryTagItem) : DiaryCreateTagResult
    data class Error(val code: String?, val message: String?) : DiaryCreateTagResult
}

sealed interface DiaryPlanResult {
    data class Success(val items: List<DiaryPlanItem>) : DiaryPlanResult
    data class Error(val code: String?, val message: String?) : DiaryPlanResult
}

sealed interface DiaryGroupsResult {
    data class Success(val groups: List<DiaryGroupItem>) : DiaryGroupsResult
    data class Error(val code: String?, val message: String?) : DiaryGroupsResult
}

sealed interface DiaryActivityParticipantsResult {
    data class Success(val participantIds: Set<String>) : DiaryActivityParticipantsResult
    data class Error(val code: String?, val message: String?) : DiaryActivityParticipantsResult
}

sealed interface DiaryAccidentsResult {
    data class Success(val items: List<DiaryAccidentItem>) : DiaryAccidentsResult
    data class Error(val code: String?, val message: String?) : DiaryAccidentsResult
}

sealed interface MemberActivityStatsResult {
    data class Success(
        val stats: List<MemberActivityStatItem>,
        val lastParticipations: List<MemberParticipationItem>
    ) : MemberActivityStatsResult
    data class Error(val code: String?, val message: String?) : MemberActivityStatsResult
}

sealed interface PredefinedActivitiesResult {
    data class Success(val items: List<PredefinedActivityItem>) : PredefinedActivitiesResult
    data class Error(val code: String?, val message: String?) : PredefinedActivitiesResult
}

sealed interface PredefinedActivityDetailResult {
    data class Success(val item: PredefinedActivityItem) : PredefinedActivityDetailResult
    data class Error(val code: String?, val message: String?) : PredefinedActivityDetailResult
}

sealed interface PredefinedActivityActionResult {
    data class Success(val message: String?) : PredefinedActivityActionResult
    data class Error(val code: String?, val message: String?) : PredefinedActivityActionResult
}

sealed interface TrainingStatsResult {
    data class Success(val data: TrainingStatsData) : TrainingStatsResult
    data class Error(val code: String?, val message: String?) : TrainingStatsResult
}

sealed interface ScheduleTeamsResult {
    data class Success(val teams: List<ScheduleTeamItem>) : ScheduleTeamsResult
    data class Error(val code: String?, val message: String?) : ScheduleTeamsResult
}

sealed interface ScheduleMatchesResult {
    data class Success(val matches: List<ScheduleMatchItem>) : ScheduleMatchesResult
    data class Error(val code: String?, val message: String?) : ScheduleMatchesResult
}

sealed interface ScheduleLeagueTableResult {
    data class Success(val rows: List<ScheduleLeagueTableRow>) : ScheduleLeagueTableResult
    data class Error(val code: String?, val message: String?) : ScheduleLeagueTableResult
}

sealed interface ScheduleActionResult {
    data class Success(val message: String?) : ScheduleActionResult
    data class Error(val code: String?, val message: String?) : ScheduleActionResult
}

sealed interface TournamentListResult {
    data class Success(val items: List<TournamentItem>) : TournamentListResult
    data class Error(val code: String?, val message: String?) : TournamentListResult
}

sealed interface TournamentDetailResult {
    data class Success(val item: TournamentItem) : TournamentDetailResult
    data class Error(val code: String?, val message: String?) : TournamentDetailResult
}

sealed interface TournamentParticipantsResult {
    data class Success(val items: List<TournamentParticipantItem>) : TournamentParticipantsResult
    data class Error(val code: String?, val message: String?) : TournamentParticipantsResult
}

sealed interface TournamentMatchesResult {
    data class Success(val items: List<TournamentMatchItem>) : TournamentMatchesResult
    data class Error(val code: String?, val message: String?) : TournamentMatchesResult
}

sealed interface TournamentActionResult {
    data class Success(val message: String?) : TournamentActionResult
    data class Error(val code: String?, val message: String?) : TournamentActionResult
}

sealed interface PermissionRolesResult {
    data class Success(val items: List<PermissionRoleItem>) : PermissionRolesResult
    data class Error(val code: String?, val message: String?) : PermissionRolesResult
}

sealed interface PermissionStructureResult {
    data class Success(val items: Map<String, PermissionResourceItem>) : PermissionStructureResult
    data class Error(val code: String?, val message: String?) : PermissionStructureResult
}

sealed interface PermissionMembersResult {
    data class Success(val items: List<PermissionMemberItem>) : PermissionMembersResult
    data class Error(val code: String?, val message: String?) : PermissionMembersResult
}

sealed interface PermissionActionResult {
    data class Success(val message: String?) : PermissionActionResult
    data class Error(val code: String?, val message: String?) : PermissionActionResult
}

sealed interface ClubTeamsResult {
    data class Success(val items: List<ClubTeamItem>) : ClubTeamsResult
    data class Error(val code: String?, val message: String?) : ClubTeamsResult
}

sealed interface ClubLeaguesResult {
    data class Success(val items: List<ClubLeagueItem>) : ClubLeaguesResult
    data class Error(val code: String?, val message: String?) : ClubLeaguesResult
}

sealed interface ClubTeamActionResult {
    data class Success(val message: String?, val teamId: String?) : ClubTeamActionResult
    data class Error(val code: String?, val message: String?) : ClubTeamActionResult
}

sealed interface TeamDocumentsResult {
    data class Success(val items: List<TeamDocumentItem>) : TeamDocumentsResult
    data class Error(val code: String?, val message: String?) : TeamDocumentsResult
}

sealed interface TeamDocumentParseResult {
    data class Success(val payload: JsonElement) : TeamDocumentParseResult
    data class Error(val code: String?, val message: String?) : TeamDocumentParseResult
}

sealed interface TeamDocumentUploadResult {
    data class Success(val documentId: String?, val message: String?) : TeamDocumentUploadResult
    data class Error(val code: String?, val message: String?) : TeamDocumentUploadResult
}

sealed interface SchedulerJobsResult {
    data class Success(val data: SchedulerJobsOverview) : SchedulerJobsResult
    data class Error(val code: String?, val message: String?) : SchedulerJobsResult
}

sealed interface TeamPlayerStatsResult {
    data class Success(val items: List<TeamPlayerStatItem>) : TeamPlayerStatsResult
    data class Error(val code: String?, val message: String?) : TeamPlayerStatsResult
}

sealed interface MyTischtennisAccountResult {
    data class Success(val account: MyTischtennisAccountData?) : MyTischtennisAccountResult
    data class Error(val code: String?, val message: String?) : MyTischtennisAccountResult
}

sealed interface MyTischtennisStatusResult {
    data class Success(val status: MyTischtennisStatusData) : MyTischtennisStatusResult
    data class Error(val code: String?, val message: String?) : MyTischtennisStatusResult
}

sealed interface MyTischtennisActionResult {
    data class Success(val message: String?, val payload: JsonObject?) : MyTischtennisActionResult
    data class Error(val code: String?, val message: String?) : MyTischtennisActionResult
}

sealed interface LogsResult {
    data class Success(val data: LogsPageData) : LogsResult
    data class Error(val code: String?, val message: String?) : LogsResult
}

sealed interface LogDetailResult {
    data class Success(val item: LogDetailItem) : LogDetailResult
    data class Error(val code: String?, val message: String?) : LogDetailResult
}

sealed interface OfficialTournamentsResult {
    data class Success(val items: List<OfficialTournamentItem>) : OfficialTournamentsResult
    data class Error(val code: String?, val message: String?) : OfficialTournamentsResult
}

sealed interface OfficialTournamentSummaryResult {
    data class Success(val data: OfficialTournamentSummary) : OfficialTournamentSummaryResult
    data class Error(val code: String?, val message: String?) : OfficialTournamentSummaryResult
}

sealed interface OfficialTournamentUploadResult {
    data class Success(val tournamentId: String?) : OfficialTournamentUploadResult
    data class Error(val code: String?, val message: String?) : OfficialTournamentUploadResult
}

sealed interface OfficialTournamentDetailResult {
    data class Success(val data: OfficialTournamentDetailData) : OfficialTournamentDetailResult
    data class Error(val code: String?, val message: String?) : OfficialTournamentDetailResult
}

sealed interface OfficialTournamentActionResult {
    data class Success(val message: String?) : OfficialTournamentActionResult
    data class Error(val code: String?, val message: String?) : OfficialTournamentActionResult
}

data class DomainSocketEvent(
    val type: DomainSocketEventType,
    val rawType: String,
    val payload: JsonElement?
)

enum class DomainSocketEventType {
    ParticipantAdded,
    ParticipantRemoved,
    ParticipantUpdated,
    DiaryNoteAdded,
    DiaryNoteUpdated,
    DiaryNoteDeleted,
    DiaryTagAdded,
    DiaryTagRemoved,
    DiaryDateUpdated,
    ActivityMemberAdded,
    ActivityMemberRemoved,
    ActivityChanged,
    MemberChanged,
    GroupChanged,
    TournamentChanged,
    ScheduleMatchUpdated,
    ScheduleMatchReportSubmitted,
    Unknown
}

sealed interface MemberImagesResult {
    data class Success(val images: List<MemberImageItem>) : MemberImagesResult
    data class Error(val code: String?, val message: String?) : MemberImagesResult
}

sealed interface MemberTrainingGroupsResult {
    data class Success(val groups: List<TrainingGroupItem>) : MemberTrainingGroupsResult
    data class Error(val code: String?, val message: String?) : MemberTrainingGroupsResult
}

sealed interface MemberNotesResult {
    data class Success(val notes: List<MemberNoteItem>) : MemberNotesResult
    data class Error(val code: String?, val message: String?) : MemberNotesResult
}

sealed interface MemberTransferConfigResult {
    data class Success(val config: MemberTransferConfig?) : MemberTransferConfigResult
    data class Error(val message: String) : MemberTransferConfigResult
}

sealed interface MemberTransferActionResult {
    data class Success(val message: String?, val configId: String?) : MemberTransferActionResult
    data class Error(val message: String) : MemberTransferActionResult
}

sealed interface MemberTransferExecutionResult {
    data class Success(val summary: MemberTransferSummary) : MemberTransferExecutionResult
    data class Error(val message: String, val summary: MemberTransferSummary? = null) : MemberTransferExecutionResult
}

sealed interface MemberSaveResult {
    data class Success(val message: String?) : MemberSaveResult
    data class Error(val code: String?, val message: String?) : MemberSaveResult
}

sealed interface MemberActionResult {
    data class Success(val message: String?) : MemberActionResult
    data class Error(val code: String?, val message: String?) : MemberActionResult
}

internal data class BackendError(
    val code: String?,
    val message: String?
)
