package de.trainingstagebuch.app.repository

import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import de.trainingstagebuch.app.utils.JsonSafeUtils

internal object RepositoryMappers {
    fun parseErrorPayload(raw: String): BackendError? {
        val obj = JsonSafeUtils.parseObject(raw) ?: return null
        return BackendError(
            code = JsonSafeUtils.getString(obj, "code"),
            message = JsonSafeUtils.getString(obj, "error", "message")
        )
    }

    fun mapClubsToHomeData(clubs: JsonElement): HomeData {
        val array = JsonSafeUtils.asArray(clubs)
        val mappedClubs = array.mapNotNull { element ->
            val obj = element as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "clubId")
                ?.trim()
                ?.takeIf { it.isNotBlank() }
                ?: return@mapNotNull null
            val name = JsonSafeUtils.getString(obj, "name")
                ?.trim()
                ?.takeIf { it.isNotBlank() }
                ?: id
            HomeClub(id = id, name = name)
        }
        val names = mappedClubs.map { it.name }
        return HomeData(
            clubCount = array.size,
            clubNames = names,
            clubs = mappedClubs
        )
    }

    fun mapMembersToMemberItems(members: JsonElement): List<MemberItem> {
        val array = JsonSafeUtils.asArray(members)
        return array.mapNotNull { element ->
            val obj = element as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id") ?: return@mapNotNull null
            val firstName = JsonSafeUtils.getString(obj, "firstName", "firstname").orEmpty().trim()
            val lastName = JsonSafeUtils.getString(obj, "lastName", "lastname").orEmpty().trim()
            val active = JsonSafeUtils.getString(obj, "active")
                ?.equals("true", ignoreCase = true)
                ?: true
            val testMembership = JsonSafeUtils.getString(obj, "testMembership")
                ?.equals("true", ignoreCase = true)
                ?: false
            val contacts = JsonSafeUtils.asArray(obj["contacts"]).mapNotNull { rawContact ->
                val contactObj = rawContact as? JsonObject ?: return@mapNotNull null
                val type = JsonSafeUtils.getString(contactObj, "type")?.lowercase() ?: return@mapNotNull null
                val value = JsonSafeUtils.getString(contactObj, "value") ?: return@mapNotNull null
                MemberContactItem(
                    type = type,
                    value = value
                )
            }

            val displayName = listOf(firstName, lastName)
                .filter { it.isNotBlank() }
                .joinToString(" ")
                .ifBlank { id }

            MemberItem(
                id = id,
                firstName = firstName,
                lastName = lastName,
                displayName = displayName,
                active = active,
                testMembership = testMembership,
                contacts = contacts
            )
        }
    }

    fun mapMemberGalleryImages(gallery: JsonElement, memberId: String): List<MemberImageItem> {
        val array = JsonSafeUtils.asArray(gallery)
        return array.mapNotNull { element ->
            val obj = element as? JsonObject ?: return@mapNotNull null
            val imageId = JsonSafeUtils.getString(obj, "imageId", "id", "_id") ?: return@mapNotNull null
            val itemMemberId = JsonSafeUtils.getString(obj, "memberId")
                ?: runCatching {
                    val memberObj = obj["member"] as? JsonObject
                    memberObj?.let { JsonSafeUtils.getString(it, "id") }
                }.getOrNull()
                ?: return@mapNotNull null
            if (itemMemberId != memberId) return@mapNotNull null

            val url = JsonSafeUtils.getString(obj, "url", "imageUrl", "latestImageUrl", "path")
            val isPrimary = JsonSafeUtils.getString(obj, "primary", "isPrimary")
                ?.equals("true", ignoreCase = true)
                ?: false

            MemberImageItem(
                imageId = imageId,
                memberId = itemMemberId,
                url = url,
                isPrimary = isPrimary
            )
        }.sortedWith(compareByDescending<MemberImageItem> { it.isPrimary }.thenBy { it.imageId })
    }

    fun mapTrainingGroups(groups: JsonElement): List<TrainingGroupItem> {
        return JsonSafeUtils.asArray(groups).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val name = JsonSafeUtils.getString(obj, "name")
                ?: JsonSafeUtils.getString(obj, "title")
                ?: id
            TrainingGroupItem(id = id, name = name)
        }
    }

    fun mapMemberNotes(notes: JsonElement): List<MemberNoteItem> {
        return JsonSafeUtils.asArray(notes).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val content = JsonSafeUtils.getString(obj, "content", "text", "note")
                ?.trim()
                ?.takeIf { it.isNotBlank() }
                ?: return@mapNotNull null
            val createdAt = JsonSafeUtils.getString(obj, "createdAt", "created_at", "date")
            MemberNoteItem(
                id = id,
                content = content,
                createdAt = createdAt
            )
        }
    }

    fun mapMemberTransferConfig(config: JsonObject): MemberTransferConfig {
        val loginCredentialsObj = config["loginCredentials"] as? JsonObject
        val additional = loginCredentialsObj
            ?.entries
            ?.filter { it.key != "username" && it.key != "password" }
            ?.mapNotNull { entry ->
                val value = JsonSafeUtils.getString(entry.value)
                if (value.isNullOrBlank()) null else "${entry.key}:$value"
            }
            ?: emptyList()

        return MemberTransferConfig(
            id = JsonSafeUtils.getString(config, "id"),
            server = JsonSafeUtils.getString(config, "server").orEmpty(),
            loginEndpoint = JsonSafeUtils.getString(config, "loginEndpoint"),
            loginFormat = JsonSafeUtils.getString(config, "loginFormat").orEmpty().ifBlank { "json" },
            loginUsername = loginCredentialsObj?.let { JsonSafeUtils.getString(it, "username") },
            loginPassword = null,
            loginAdditionalField1 = additional.getOrNull(0),
            loginAdditionalField2 = additional.getOrNull(1),
            transferEndpoint = JsonSafeUtils.getString(config, "transferEndpoint").orEmpty(),
            transferMethod = JsonSafeUtils.getString(config, "transferMethod").orEmpty().ifBlank { "POST" },
            transferFormat = JsonSafeUtils.getString(config, "transferFormat").orEmpty().ifBlank { "json" },
            transferTemplate = JsonSafeUtils.getString(config, "transferTemplate").orEmpty(),
            useBulkMode = JsonSafeUtils.getString(config, "useBulkMode")?.equals("true", ignoreCase = true) ?: false,
            bulkWrapperTemplate = JsonSafeUtils.getString(config, "bulkWrapperTemplate")
        )
    }

    fun mapMemberTransferSummary(response: JsonObject): MemberTransferSummary {
        val transferred = numberOrStringInt(response, "transferred")
        val total = numberOrStringInt(response, "total")

        val invalidMembers = JsonSafeUtils.asArray(response["invalidMembers"])
            .mapNotNull { raw ->
                val obj = raw as? JsonObject ?: return@mapNotNull null
                val memberObj = obj["member"] as? JsonObject
                val firstName = memberObj?.let { JsonSafeUtils.getString(it, "firstName") }.orEmpty()
                val lastName = memberObj?.let { JsonSafeUtils.getString(it, "lastName") }.orEmpty()
                listOf(firstName, lastName).filter { it.isNotBlank() }.joinToString(" ").ifBlank {
                    memberObj?.let { JsonSafeUtils.getString(it, "id") } ?: "Unknown"
                }
            }

        val errors = JsonSafeUtils.asArray(response["errors"])
            .mapNotNull { raw ->
                val obj = raw as? JsonObject ?: return@mapNotNull JsonSafeUtils.getString(raw)
                val member = JsonSafeUtils.getString(obj, "member").orEmpty()
                val error = JsonSafeUtils.getString(obj, "error").orEmpty()
                listOf(member, error).filter { it.isNotBlank() }.joinToString(": ").ifBlank { null }
            }

        return MemberTransferSummary(
            success = JsonSafeUtils.getString(response, "success")?.equals("true", ignoreCase = true) ?: false,
            message = JsonSafeUtils.getString(response, "message")
                ?: JsonSafeUtils.getString(response, "error"),
            transferred = transferred,
            total = total,
            invalidMembers = invalidMembers,
            errors = errors
        )
    }

    fun mapClubDetails(club: JsonObject): ClubDetails {
        val id = JsonSafeUtils.getString(club, "id", "_id")
        val name = JsonSafeUtils.getString(club, "name").orEmpty()
        val members = mapMembersToMemberItems(club["members"] ?: JsonArray(emptyList()))
        return ClubDetails(
            id = id,
            name = name,
            members = members
        )
    }

    fun mapClubSettings(club: JsonObject): ClubSettingsData {
        val greetingText = JsonSafeUtils.getString(club, "greetingText")
            ?: (club["settings"] as? JsonObject)?.let { JsonSafeUtils.getString(it, "greetingText") }
            ?: ""
        val associationMemberNumber = JsonSafeUtils.getString(club, "associationMemberNumber")
            ?: (club["settings"] as? JsonObject)?.let { JsonSafeUtils.getString(it, "associationMemberNumber") }
            ?: ""

        return ClubSettingsData(
            greetingText = greetingText,
            associationMemberNumber = associationMemberNumber
        )
    }

    fun mapClubTrainingGroups(groups: JsonElement): List<ClubTrainingGroup> {
        return JsonSafeUtils.asArray(groups).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val name = JsonSafeUtils.getString(obj, "name")?.trim().orEmpty().ifBlank { id }
            ClubTrainingGroup(id = id, name = name)
        }
    }

    fun mapClubTrainingTimeGroups(groups: JsonElement): List<ClubTrainingTimeGroup> {
        return JsonSafeUtils.asArray(groups).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val name = JsonSafeUtils.getString(obj, "name")?.trim().orEmpty().ifBlank { id }
            val times = JsonSafeUtils.asArray(obj["trainingTimes"]).mapNotNull { rawTime ->
                val timeObj = rawTime as? JsonObject ?: return@mapNotNull null
                val timeId = JsonSafeUtils.getString(timeObj, "id", "_id") ?: return@mapNotNull null
                val weekday = JsonSafeUtils.getString(timeObj, "weekday")?.toIntOrNull() ?: 0
                val startTime = JsonSafeUtils.getString(timeObj, "startTime").orEmpty()
                val endTime = JsonSafeUtils.getString(timeObj, "endTime").orEmpty()
                ClubTrainingTime(
                    id = timeId,
                    weekday = weekday,
                    startTime = startTime,
                    endTime = endTime
                )
            }
            ClubTrainingTimeGroup(
                id = id,
                name = name,
                trainingTimes = times
            )
        }
    }

    fun mapPendingApprovals(entries: JsonElement): List<PendingApprovalUser> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val userObj = (obj["user"] as? JsonObject) ?: obj
            val id = JsonSafeUtils.getString(userObj, "id", "_id") ?: return@mapNotNull null
            val firstName = JsonSafeUtils.getString(userObj, "firstName", "firstname").orEmpty()
            val lastName = JsonSafeUtils.getString(userObj, "lastName", "lastname").orEmpty()
            val email = JsonSafeUtils.getString(userObj, "email")
            PendingApprovalUser(
                id = id,
                firstName = firstName,
                lastName = lastName,
                email = email
            )
        }
    }

    fun mapPermissionRoles(entries: JsonElement): List<PermissionRoleItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val value = JsonSafeUtils.getString(obj, "value") ?: return@mapNotNull null
            PermissionRoleItem(
                value = value,
                label = JsonSafeUtils.getString(obj, "label").orEmpty().ifBlank { value },
                description = JsonSafeUtils.getString(obj, "description")
            )
        }
    }

    fun mapPermissionStructure(entry: JsonElement): Map<String, PermissionResourceItem> {
        val obj = entry as? JsonObject ?: return emptyMap()
        return obj.mapValues { (_, rawValue) ->
            val resourceObj = rawValue as? JsonObject
            val actions = JsonSafeUtils.asArray(resourceObj?.get("actions")).mapNotNull { JsonSafeUtils.getString(it) }
            PermissionResourceItem(
                label = JsonSafeUtils.getString(resourceObj ?: JsonObject(emptyMap()), "label")
                    .orEmpty()
                    .ifBlank { "Resource" },
                actions = actions
            )
        }
    }

    fun mapPermissionMembers(entries: JsonElement): List<PermissionMemberItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val userId = JsonSafeUtils.getString(obj, "userId") ?: return@mapNotNull null
            val userObj = obj["user"] as? JsonObject
            PermissionMemberItem(
                userId = userId,
                role = JsonSafeUtils.getString(obj, "role").orEmpty().ifBlank { "member" },
                approved = JsonSafeUtils.getString(obj, "approved")?.equals("true", ignoreCase = true) != false,
                isOwner = JsonSafeUtils.getString(obj, "isOwner")?.equals("true", ignoreCase = true) == true,
                email = JsonSafeUtils.getString(userObj ?: JsonObject(emptyMap()), "email"),
                firstName = JsonSafeUtils.getString(userObj ?: JsonObject(emptyMap()), "firstName", "firstname"),
                lastName = JsonSafeUtils.getString(userObj ?: JsonObject(emptyMap()), "lastName", "lastname"),
                permissions = mapPermissionStateObject(obj["permissions"]),
                effectivePermissions = mapPermissionStateObject(obj["effectivePermissions"])
            )
        }
    }

    fun mapClubTeams(entries: JsonElement): List<ClubTeamItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "clubTeamId") ?: return@mapNotNull null
            val leagueObj = obj["league"] as? JsonObject
            val seasonObj = obj["season"] as? JsonObject
            ClubTeamItem(
                id = id,
                name = JsonSafeUtils.getString(obj, "name", "teamName").orEmpty().ifBlank { id },
                leagueId = JsonSafeUtils.getString(obj, "leagueId")
                    ?: leagueObj?.let { JsonSafeUtils.getString(it, "id", "_id") },
                leagueName = JsonSafeUtils.getString(obj, "leagueName")
                    ?: leagueObj?.let { JsonSafeUtils.getString(it, "name") },
                seasonId = JsonSafeUtils.getString(obj, "seasonId")
                    ?: seasonObj?.let { JsonSafeUtils.getString(it, "id", "_id") },
                seasonName = seasonObj?.let { JsonSafeUtils.getString(it, "season", "name") },
                myTischtennisTeamId = JsonSafeUtils.getString(obj, "myTischtennisTeamId"),
                leagueAssociation = leagueObj?.let { JsonSafeUtils.getString(it, "association") },
                leagueGroupName = leagueObj?.let { JsonSafeUtils.getString(it, "groupname") },
                leagueGroupId = leagueObj?.let { JsonSafeUtils.getString(it, "myTischtennisGroupId") },
                createdAt = JsonSafeUtils.getString(obj, "createdAt")
            )
        }
    }

    fun mapClubLeagues(entries: JsonElement): List<ClubLeagueItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "leagueId") ?: return@mapNotNull null
            ClubLeagueItem(
                id = id,
                name = JsonSafeUtils.getString(obj, "name").orEmpty().ifBlank { id },
                seasonId = JsonSafeUtils.getString(obj, "seasonId")
            )
        }
    }

    fun mapTeamDocuments(entries: JsonElement): List<TeamDocumentItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            TeamDocumentItem(
                id = id,
                clubTeamId = JsonSafeUtils.getString(obj, "clubTeamId").orEmpty(),
                documentType = JsonSafeUtils.getString(obj, "documentType").orEmpty(),
                fileName = JsonSafeUtils.getString(obj, "originalName", "filename", "name"),
                mimeType = JsonSafeUtils.getString(obj, "mimeType"),
                size = JsonSafeUtils.getString(obj, "size")?.toLongOrNull(),
                createdAt = JsonSafeUtils.getString(obj, "createdAt")
            )
        }
    }

    fun mapSchedulerJobs(entry: JsonElement): SchedulerJobsOverview {
        val root = entry as? JsonObject ?: return SchedulerJobsOverview()
        val data = root["data"] as? JsonObject ?: root
        return SchedulerJobsOverview(
            ratingUpdates = mapSchedulerJob(data["rating_updates"] as? JsonObject),
            matchResults = mapSchedulerJob(data["match_results"] as? JsonObject)
        )
    }

    fun mapPlayerStats(entries: JsonElement): List<TeamPlayerStatItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val memberId = JsonSafeUtils.getString(obj, "memberId") ?: return@mapNotNull null
            TeamPlayerStatItem(
                memberId = memberId,
                firstName = JsonSafeUtils.getString(obj, "firstName", "firstname").orEmpty(),
                lastName = JsonSafeUtils.getString(obj, "lastName", "lastname").orEmpty(),
                totalSeason = JsonSafeUtils.getString(obj, "totalSeason")?.toIntOrNull() ?: 0,
                totalFirstHalf = JsonSafeUtils.getString(obj, "totalFirstHalf")?.toIntOrNull() ?: 0,
                totalSecondHalf = JsonSafeUtils.getString(obj, "totalSecondHalf")?.toIntOrNull() ?: 0
            )
        }
    }

    fun mapOfficialTournaments(entries: JsonElement): List<OfficialTournamentItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            OfficialTournamentItem(
                id = id,
                name = JsonSafeUtils.getString(obj, "name", "title").orEmpty().ifBlank { id },
                date = JsonSafeUtils.getString(obj, "date", "startDate"),
                location = JsonSafeUtils.getString(obj, "location", "city"),
                status = JsonSafeUtils.getString(obj, "status")
            )
        }
    }

    fun mapOfficialTournamentSummary(entry: JsonElement): OfficialTournamentSummary {
        if (entry is JsonArray) {
            val totalEntries = entry.sumOf { item ->
                val obj = item as? JsonObject ?: return@sumOf 0
                JsonSafeUtils.asArray(obj["entries"]).size
            }
            return OfficialTournamentSummary(
                total = entry.size,
                plannedParticipations = totalEntries
            )
        }
        val obj = entry as? JsonObject ?: return OfficialTournamentSummary(0, 0)
        return OfficialTournamentSummary(
            total = JsonSafeUtils.getString(obj, "total")?.toIntOrNull() ?: 0,
            plannedParticipations = JsonSafeUtils.getString(obj, "plannedParticipations", "planned")?.toIntOrNull() ?: 0
        )
    }

    fun mapOfficialTournamentDetail(entry: JsonElement): OfficialTournamentDetailData? {
        val root = entry as? JsonObject ?: return null
        val parsedData = root["parsedData"] as? JsonObject ?: return null
        val competitions = JsonSafeUtils.asArray(parsedData["competitions"]).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id")?.toIntOrNull() ?: return@mapNotNull null
            OfficialCompetitionItem(
                id = id,
                name = JsonSafeUtils.getString(obj, "ageClassCompetition", "altersklasseWettbewerb").orEmpty(),
                startTime = JsonSafeUtils.getString(obj, "startTime", "startzeit"),
                entryFee = JsonSafeUtils.getString(obj, "entryFee", "startgeld")
            )
        }
        val participation = JsonSafeUtils.asArray(root["participation"]).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val competitionId = JsonSafeUtils.getString(obj, "competitionId")?.toIntOrNull() ?: return@mapNotNull null
            val memberId = JsonSafeUtils.getString(obj, "memberId") ?: return@mapNotNull null
            OfficialParticipationItem(
                competitionId = competitionId,
                memberId = memberId,
                wants = jsonBool(obj, "wants"),
                registered = jsonBool(obj, "registered"),
                participated = jsonBool(obj, "participated"),
                placement = JsonSafeUtils.getString(obj, "placement")
            )
        }
        return OfficialTournamentDetailData(
            id = JsonSafeUtils.getString(root, "id", "_id").orEmpty(),
            title = JsonSafeUtils.getString(parsedData, "title"),
            termin = JsonSafeUtils.getString(parsedData, "termin"),
            competitions = competitions,
            participation = participation
        )
    }

    fun mapLogsPage(entry: JsonElement): LogsPageData {
        val root = entry as? JsonObject ?: return LogsPageData()
        val dataObj = (root["data"] as? JsonObject) ?: root
        val logsRaw = dataObj["logs"] ?: dataObj["items"] ?: dataObj["entries"] ?: JsonArray(emptyList())
        val logs = mapLogs(logsRaw)
        val total = JsonSafeUtils.getString(dataObj, "total", "count")?.toIntOrNull() ?: logs.size
        return LogsPageData(
            logs = logs,
            total = total
        )
    }

    fun mapLogs(entry: JsonElement): List<LogItem> {
        return JsonSafeUtils.asArray(entry).mapNotNull { raw ->
            mapLogItem(raw)
        }
    }

    fun mapLogDetail(entry: JsonElement): LogDetailItem? {
        val root = entry as? JsonObject ?: return null
        val logObj = (root["data"] as? JsonObject) ?: root
        val base = mapLogItem(logObj) ?: return null
        return LogDetailItem(
            id = base.id,
            createdAt = base.createdAt,
            logType = base.logType,
            method = base.method,
            path = base.path,
            statusCode = base.statusCode,
            executionTime = base.executionTime,
            errorMessage = base.errorMessage,
            ipAddress = JsonSafeUtils.getString(logObj, "ipAddress", "ip"),
            schedulerJobType = JsonSafeUtils.getString(logObj, "schedulerJobType"),
            requestBody = JsonSafeUtils.getString(logObj, "requestBody"),
            responseBody = JsonSafeUtils.getString(logObj, "responseBody")
        )
    }

    fun mapMyTischtennisAccount(entry: JsonElement): MyTischtennisAccountData? {
        val root = entry as? JsonObject ?: return null
        val account = (root["account"] as? JsonObject) ?: root
        val email = JsonSafeUtils.getString(account, "email")
            ?: JsonSafeUtils.getString(account, "username")
            ?: return null
        return MyTischtennisAccountData(
            email = email,
            clubId = JsonSafeUtils.getString(account, "clubId"),
            clubName = JsonSafeUtils.getString(account, "clubName"),
            fedNickname = JsonSafeUtils.getString(account, "fedNickname"),
            lastLoginSuccess = JsonSafeUtils.getString(account, "lastLoginSuccess"),
            lastLoginAttempt = JsonSafeUtils.getString(account, "lastLoginAttempt")
        )
    }

    fun mapMyTischtennisStatus(entry: JsonElement): MyTischtennisStatusData {
        val root = entry as? JsonObject ?: return MyTischtennisStatusData(hasPassword = false, configured = false)
        val status = (root["data"] as? JsonObject) ?: root
        return MyTischtennisStatusData(
            hasPassword = jsonBool(status, "hasPassword"),
            configured = jsonBool(status, "configured")
        )
    }

    fun mapDiaryDates(entries: JsonElement): List<DiaryDateEntry> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            mapDiaryDate(raw)
        }
    }

    private fun mapLogItem(raw: JsonElement): LogItem? {
        val obj = raw as? JsonObject ?: return null
        val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return null
        return LogItem(
            id = id,
            createdAt = JsonSafeUtils.getString(obj, "createdAt"),
            logType = JsonSafeUtils.getString(obj, "logType").orEmpty().ifBlank { "manual" },
            method = JsonSafeUtils.getString(obj, "method").orEmpty().ifBlank { "GET" },
            path = JsonSafeUtils.getString(obj, "path").orEmpty(),
            statusCode = JsonSafeUtils.getString(obj, "statusCode")?.toIntOrNull(),
            executionTime = JsonSafeUtils.getString(obj, "executionTime")?.toLongOrNull(),
            errorMessage = JsonSafeUtils.getString(obj, "errorMessage", "error")
        )
    }

    fun mapDiaryDate(raw: JsonElement): DiaryDateEntry? {
        val obj = raw as? JsonObject ?: return null
        val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return null
        val date = JsonSafeUtils.getString(obj, "date") ?: return null
        val tags = JsonSafeUtils.asArray(obj["diaryTags"]).mapNotNull { rawTag ->
            mapTag(rawTag)
        }
        return DiaryDateEntry(
            id = id,
            date = date,
            trainingStart = JsonSafeUtils.getString(obj, "trainingStart"),
            trainingEnd = JsonSafeUtils.getString(obj, "trainingEnd"),
            tags = tags
        )
    }

    fun mapDiaryParticipants(entries: JsonElement): List<DiaryParticipant> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val memberId = JsonSafeUtils.getString(obj, "memberId") ?: return@mapNotNull null
            val groupId = JsonSafeUtils.getString(obj, "groupId")
            DiaryParticipant(id = id, memberId = memberId, groupId = groupId)
        }
    }

    fun mapDiaryActivities(entries: JsonElement): List<DiaryActivityItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            mapDiaryActivity(raw)
        }
    }

    fun mapDiaryActivity(raw: JsonElement): DiaryActivityItem? {
        val obj = raw as? JsonObject ?: return null
        val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return null
        val description = JsonSafeUtils.getString(obj, "description", "activity")
            ?.trim()
            ?.takeIf { it.isNotBlank() }
            ?: return null
        return DiaryActivityItem(id = id, description = description)
    }

    private fun numberOrStringInt(obj: JsonObject, key: String): Int {
        return obj[key]?.let { element ->
            JsonSafeUtils.getString(element)?.toIntOrNull()
                ?: runCatching { element.toString().trim('"').toInt() }.getOrNull()
        } ?: 0
    }

    fun mapTags(entries: JsonElement): List<DiaryTagItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            mapTag(raw)
        }
    }

    fun mapDiaryPlanItems(entries: JsonElement): List<DiaryPlanItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val isTimeblock = JsonSafeUtils.getString(obj, "isTimeblock")
                ?.equals("true", ignoreCase = true)
                ?: false
            val activity = JsonSafeUtils.getString(obj, "activity", "customActivityName")
                ?: (obj["predefinedActivity"] as? JsonObject)?.let {
                    JsonSafeUtils.getString(it, "name", "code")
                }
                ?: ""
            val duration = JsonSafeUtils.getString(obj, "duration")
            val durationText = JsonSafeUtils.getString(obj, "durationText")
            val groupId = JsonSafeUtils.getString(obj, "groupId")
            val orderId = JsonSafeUtils.getString(obj, "orderId")?.toIntOrNull()
            val predefinedActivityId = JsonSafeUtils.getString(obj, "predefinedActivityId")
                ?: (obj["predefinedActivity"] as? JsonObject)?.let {
                    JsonSafeUtils.getString(it, "id", "_id")
                }
            DiaryPlanItem(
                id = id,
                activity = activity,
                duration = duration,
                durationText = durationText,
                isTimeblock = isTimeblock,
                groupId = groupId,
                orderId = orderId,
                predefinedActivityId = predefinedActivityId
            )
        }
    }

    fun mapDiaryGroups(entries: JsonElement): List<DiaryGroupItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            val name = JsonSafeUtils.getString(obj, "name")
                ?.trim()
                ?.takeIf { it.isNotBlank() }
                ?: id
            val lead = JsonSafeUtils.getString(obj, "lead").orEmpty()
            DiaryGroupItem(id = id, name = name, lead = lead)
        }
    }

    fun mapTag(raw: JsonElement): DiaryTagItem? {
        val obj = raw as? JsonObject ?: return null
        val nestedTag = obj["tag"] as? JsonObject
        val source = nestedTag ?: obj
        val id = JsonSafeUtils.getString(source, "id", "_id") ?: return null
        val name = JsonSafeUtils.getString(source, "name", "label")
            ?.trim()
            ?.takeIf { it.isNotBlank() }
            ?: return null
        return DiaryTagItem(id = id, name = name)
    }

    fun mapParticipantIds(entries: JsonElement): Set<String> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            JsonSafeUtils.getString(obj, "participantId")
        }.toSet()
    }

    fun mapAccidents(entries: JsonElement): List<DiaryAccidentItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            DiaryAccidentItem(
                id = id,
                accident = JsonSafeUtils.getString(obj, "accident", "description").orEmpty(),
                happenedAt = JsonSafeUtils.getString(obj, "createdAt", "date")
            )
        }
    }

    fun mapMemberActivityStats(entries: JsonElement): List<MemberActivityStatItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val activity = JsonSafeUtils.getString(obj, "activity", "name") ?: return@mapNotNull null
            val count = JsonSafeUtils.getString(obj, "count", "value")?.toIntOrNull() ?: 0
            MemberActivityStatItem(activity = activity, count = count)
        }
    }

    fun mapLastParticipations(entries: JsonElement): List<MemberParticipationItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val date = JsonSafeUtils.getString(obj, "date", "diaryDate") ?: return@mapNotNull null
            val activity = JsonSafeUtils.getString(obj, "activity", "name").orEmpty()
            MemberParticipationItem(
                date = date,
                activity = activity
            )
        }
    }

    fun mapPredefinedActivities(entries: JsonElement): List<PredefinedActivityItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            mapPredefinedActivity(obj)
        }
    }

    fun mapPredefinedActivity(entry: JsonObject): PredefinedActivityItem? {
        val id = JsonSafeUtils.getString(entry, "id", "_id") ?: return null
        val name = JsonSafeUtils.getString(entry, "name").orEmpty()
        val code = JsonSafeUtils.getString(entry, "code")
        val duration = JsonSafeUtils.getString(entry, "duration")
        val durationText = JsonSafeUtils.getString(entry, "durationText")
        val description = JsonSafeUtils.getString(entry, "description")
        val imageLink = JsonSafeUtils.getString(entry, "imageLink")
        val drawingData = entry["drawingData"]?.toString()
        val images = JsonSafeUtils.asArray(entry["images"]).mapNotNull { raw ->
            val imageObj = raw as? JsonObject ?: return@mapNotNull null
            val imageId = JsonSafeUtils.getString(imageObj, "id", "_id") ?: return@mapNotNull null
            val url = JsonSafeUtils.getString(imageObj, "imageLink", "url")
            val imageDrawingData = imageObj["drawingData"]?.toString()
            PredefinedActivityImage(imageId = imageId, url = url, drawingData = imageDrawingData)
        }
        return PredefinedActivityItem(
            id = id,
            name = name,
            code = code,
            duration = duration,
            durationText = durationText,
            description = description,
            imageLink = imageLink,
            drawingData = drawingData,
            images = images
        )
    }

    fun mapTrainingStats(entry: JsonObject): TrainingStatsData {
        val members = JsonSafeUtils.asArray(entry["members"]).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id") ?: return@mapNotNull null
            TrainingStatsMember(
                id = id,
                firstName = JsonSafeUtils.getString(obj, "firstName", "firstname").orEmpty(),
                lastName = JsonSafeUtils.getString(obj, "lastName", "lastname").orEmpty(),
                ttr = JsonSafeUtils.getString(obj, "ttr")?.toIntOrNull(),
                qttr = JsonSafeUtils.getString(obj, "qttr")?.toIntOrNull(),
                birthDate = JsonSafeUtils.getString(obj, "birthDate", "birthdate"),
                participation12Months = JsonSafeUtils.getString(obj, "participation12Months")?.toIntOrNull() ?: 0,
                participation3Months = JsonSafeUtils.getString(obj, "participation3Months")?.toIntOrNull() ?: 0,
                participationTotal = JsonSafeUtils.getString(obj, "participationTotal")?.toIntOrNull() ?: 0,
                lastTraining = JsonSafeUtils.getString(obj, "lastTraining")
            )
        }
        val days = JsonSafeUtils.asArray(entry["trainingDays"]).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id")
                ?: JsonSafeUtils.getString(obj, "date")
                ?: return@mapNotNull null
            val date = JsonSafeUtils.getString(obj, "date") ?: return@mapNotNull null
            TrainingDayStatsItem(
                id = id,
                date = date,
                participantCount = JsonSafeUtils.getString(obj, "participantCount")?.toIntOrNull() ?: 0
            )
        }
        return TrainingStatsData(
            members = members,
            trainingsCount12Months = JsonSafeUtils.getString(entry, "trainingsCount12Months")?.toIntOrNull() ?: 0,
            trainingsCount3Months = JsonSafeUtils.getString(entry, "trainingsCount3Months")?.toIntOrNull() ?: 0,
            trainingDays = days
        )
    }

    fun mapScheduleTeams(entries: JsonElement): List<ScheduleTeamItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "clubTeamId") ?: return@mapNotNull null
            val name = JsonSafeUtils.getString(obj, "name", "teamName")
                ?: (obj["team"] as? JsonObject)?.let { JsonSafeUtils.getString(it, "name") }
                ?: id
            val leagueObj = obj["league"] as? JsonObject
            val leagueId = JsonSafeUtils.getString(obj, "leagueId")
                ?: leagueObj?.let { JsonSafeUtils.getString(it, "id", "_id") }
            val leagueName = JsonSafeUtils.getString(obj, "leagueName")
                ?: leagueObj?.let { JsonSafeUtils.getString(it, "name") }
            ScheduleTeamItem(
                id = id,
                name = name,
                leagueId = leagueId,
                leagueName = leagueName
            )
        }
    }

    fun mapScheduleMatches(entries: JsonElement): List<ScheduleMatchItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "matchId") ?: return@mapNotNull null
            val homeTeamObj = obj["homeTeam"] as? JsonObject
            val guestTeamObj = obj["guestTeam"] as? JsonObject
            val leagueDetailsObj = obj["leagueDetails"] as? JsonObject
            val locationObj = obj["location"] as? JsonObject
            ScheduleMatchItem(
                id = id,
                date = JsonSafeUtils.getString(obj, "date"),
                time = JsonSafeUtils.getString(obj, "time", "startTime"),
                homeTeamName = JsonSafeUtils.getString(obj, "homeTeamName")
                    ?: homeTeamObj?.let { JsonSafeUtils.getString(it, "name") },
                guestTeamName = JsonSafeUtils.getString(obj, "guestTeamName")
                    ?: guestTeamObj?.let { JsonSafeUtils.getString(it, "name") },
                leagueName = JsonSafeUtils.getString(obj, "leagueName")
                    ?: leagueDetailsObj?.let { JsonSafeUtils.getString(it, "name") },
                homeMatchPoints = JsonSafeUtils.getString(obj, "homeMatchPoints")?.toIntOrNull(),
                guestMatchPoints = JsonSafeUtils.getString(obj, "guestMatchPoints")?.toIntOrNull(),
                isCompleted = jsonBool(obj, "isCompleted"),
                code = JsonSafeUtils.getString(obj, "code"),
                homePin = JsonSafeUtils.getString(obj, "homePin"),
                guestPin = JsonSafeUtils.getString(obj, "guestPin"),
                locationName = locationObj?.let { JsonSafeUtils.getString(it, "name") },
                locationAddress = locationObj?.let { JsonSafeUtils.getString(it, "address") },
                locationZip = locationObj?.let { JsonSafeUtils.getString(it, "zip") },
                locationCity = locationObj?.let { JsonSafeUtils.getString(it, "city") },
                playersReady = jsonStringList(obj, "playersReady"),
                playersPlanned = jsonStringList(obj, "playersPlanned"),
                playersPlayed = jsonStringList(obj, "playersPlayed")
            )
        }
    }

    fun mapLeagueTable(entries: JsonElement): List<ScheduleLeagueTableRow> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val teamId = JsonSafeUtils.getString(obj, "teamId", "id", "_id") ?: return@mapNotNull null
            ScheduleLeagueTableRow(
                teamId = teamId,
                teamName = JsonSafeUtils.getString(obj, "teamName", "name").orEmpty(),
                matchPoints = JsonSafeUtils.getString(obj, "matchPoints") ?: "",
                setsWon = JsonSafeUtils.getString(obj, "setsWon") ?: "",
                setsLost = JsonSafeUtils.getString(obj, "setsLost") ?: "",
                tablePoints = JsonSafeUtils.getString(obj, "tablePoints") ?: "",
                pointRatio = JsonSafeUtils.getString(obj, "pointRatio") ?: ""
            )
        }
    }

    fun mapTournaments(entries: JsonElement): List<TournamentItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            mapTournament(raw as? JsonObject ?: return@mapNotNull null)
        }
    }

    fun mapTournament(entry: JsonObject): TournamentItem? {
        val id = JsonSafeUtils.getString(entry, "id", "_id", "tournamentId") ?: return null
        return TournamentItem(
            id = id,
            name = JsonSafeUtils.getString(entry, "name", "tournamentName").orEmpty().ifBlank { id },
            date = JsonSafeUtils.getString(entry, "date"),
            winningSets = JsonSafeUtils.getString(entry, "winningSets")?.toIntOrNull() ?: 3,
            numberOfTables = JsonSafeUtils.getString(entry, "numberOfTables")?.toIntOrNull(),
            isGroupTournament = jsonBool(entry, "isGroupTournament"),
            type = JsonSafeUtils.getString(entry, "type"),
            location = JsonSafeUtils.getString(entry, "location", "ort")
        )
    }

    fun mapTournamentParticipants(entries: JsonElement): List<TournamentParticipantItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "participantId") ?: return@mapNotNull null
            val memberObj = obj["member"] as? JsonObject
            val participantObj = obj["participant"] as? JsonObject
            val firstName = JsonSafeUtils.getString(obj, "firstName", "firstname")
                ?: memberObj?.let { JsonSafeUtils.getString(it, "firstName", "firstname") }
                ?: participantObj?.let { JsonSafeUtils.getString(it, "firstName", "firstname") }
                ?: ""
            val lastName = JsonSafeUtils.getString(obj, "lastName", "lastname")
                ?: memberObj?.let { JsonSafeUtils.getString(it, "lastName", "lastname") }
                ?: participantObj?.let { JsonSafeUtils.getString(it, "lastName", "lastname") }
                ?: ""
            val name = listOf(firstName, lastName).filter { it.isNotBlank() }.joinToString(" ").ifBlank {
                JsonSafeUtils.getString(obj, "name") ?: id
            }
            TournamentParticipantItem(
                id = id,
                memberId = JsonSafeUtils.getString(obj, "memberId")
                    ?: memberObj?.let { JsonSafeUtils.getString(it, "id", "_id") },
                name = name,
                seeded = jsonBool(obj, "seeded"),
                gaveUp = jsonBool(obj, "gaveUp"),
                classId = JsonSafeUtils.getString(obj, "classId"),
                isExternal = jsonBool(obj, "isExternal")
            )
        }
    }

    fun mapTournamentMatches(entries: JsonElement): List<TournamentMatchItem> {
        return JsonSafeUtils.asArray(entries).mapNotNull { raw ->
            val obj = raw as? JsonObject ?: return@mapNotNull null
            val id = JsonSafeUtils.getString(obj, "id", "_id", "matchId") ?: return@mapNotNull null
            val player1Obj = obj["player1"] as? JsonObject
            val player2Obj = obj["player2"] as? JsonObject
            TournamentMatchItem(
                id = id,
                round = JsonSafeUtils.getString(obj, "round").orEmpty(),
                groupNumber = JsonSafeUtils.getString(obj, "groupNumber")?.toIntOrNull(),
                classId = JsonSafeUtils.getString(obj, "classId"),
                player1Name = extractPlayerName(player1Obj),
                player2Name = extractPlayerName(player2Obj),
                result = JsonSafeUtils.getString(obj, "result"),
                isFinished = jsonBool(obj, "isFinished"),
                isActive = jsonBool(obj, "isActive"),
                tableNumber = JsonSafeUtils.getString(obj, "tableNumber")?.toIntOrNull()
            )
        }
    }

    private fun extractPlayerName(playerObj: JsonObject?): String? {
        if (playerObj == null) return null
        val memberObj = playerObj["member"] as? JsonObject
        val firstName = JsonSafeUtils.getString(playerObj, "firstName", "firstname")
            ?: memberObj?.let { JsonSafeUtils.getString(it, "firstName", "firstname") }
            ?: ""
        val lastName = JsonSafeUtils.getString(playerObj, "lastName", "lastname")
            ?: memberObj?.let { JsonSafeUtils.getString(it, "lastName", "lastname") }
            ?: ""
        return listOf(firstName, lastName).filter { it.isNotBlank() }.joinToString(" ").ifBlank {
            JsonSafeUtils.getString(playerObj, "name")
                ?: memberObj?.let { JsonSafeUtils.getString(it, "name") }
        }
    }

    private fun jsonBool(obj: JsonObject, key: String): Boolean {
        return JsonSafeUtils.getString(obj, key)?.equals("true", ignoreCase = true) == true
    }

    private fun jsonStringList(obj: JsonObject, key: String): List<String> {
        val raw = obj[key] ?: return emptyList()
        return when (raw) {
            is JsonArray -> raw.mapNotNull { JsonSafeUtils.getString(it) }
            is JsonPrimitive -> {
                val text = JsonSafeUtils.getString(raw)
                if (text.isNullOrBlank()) {
                    emptyList()
                } else {
                    val parsed = JsonSafeUtils.parseObject("{\"v\":$text}")?.let { inner ->
                        JsonSafeUtils.asArray(inner["v"]).mapNotNull { JsonSafeUtils.getString(it) }
                    }
                    parsed.orEmpty()
                }
            }
            else -> emptyList()
        }
    }

    private fun mapPermissionStateObject(raw: JsonElement?): Map<String, Map<String, Boolean>> {
        val obj = raw as? JsonObject ?: return emptyMap()
        return obj.mapValues { (_, resourceValue) ->
            val resourceObj = resourceValue as? JsonObject ?: return@mapValues emptyMap()
            resourceObj.mapNotNull { (action, actionValue) ->
                val normalized = JsonSafeUtils.getString(actionValue)
                    ?.let { it.equals("true", ignoreCase = true) || it == "1" }
                normalized?.let { action to it }
            }.toMap()
        }
    }

    private fun mapSchedulerJob(raw: JsonObject?): SchedulerJobInfo? {
        if (raw == null) return null
        val details = JsonSafeUtils.asArray(raw["teamDetails"]).mapNotNull { entry ->
            val obj = entry as? JsonObject ?: return@mapNotNull null
            TeamJobDetail(
                clubTeamId = JsonSafeUtils.getString(obj, "clubTeamId").orEmpty(),
                teamName = JsonSafeUtils.getString(obj, "teamName"),
                success = JsonSafeUtils.getString(obj, "success")?.equals("true", ignoreCase = true) == true,
                lastRun = JsonSafeUtils.getString(obj, "lastRun")
            )
        }
        return SchedulerJobInfo(
            lastRun = JsonSafeUtils.getString(raw, "lastRun"),
            success = JsonSafeUtils.getString(raw, "success")?.equals("true", ignoreCase = true) == true,
            updatedCount = JsonSafeUtils.getString(raw, "updatedCount")?.toIntOrNull(),
            fetchedCount = JsonSafeUtils.getString(raw, "fetchedCount")?.toIntOrNull(),
            teamDetails = details
        )
    }
}
