package top.r3944realms.ltdmanager.module.gitea

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class GiteaUser(
    val id: Long = 0,
    val login: String = "",
    @SerialName("login_name") val loginName: String = "",
    @SerialName("full_name") val fullName: String = "",
    val email: String = "",
    @SerialName("avatar_url") val avatarUrl: String = "",
    val username: String = "",
)

@Serializable
data class GiteaRepository(
    val id: Long = 0,
    val name: String = "",
    @SerialName("full_name") val fullName: String = "",
    val owner: GiteaUser = GiteaUser(),
    @SerialName("html_url") val htmlUrl: String = "",
    val description: String = "",
    @SerialName("ssh_url") val sshUrl: String = "",
    @SerialName("clone_url") val cloneUrl: String = "",
    @SerialName("default_branch") val defaultBranch: String = "",
    val private: Boolean = false,
    val website: String = "",
)

@Serializable
data class GiteaCommit(
    val id: String = "",
    val message: String = "",
    val url: String = "",
    val author: GiteaUser = GiteaUser(),
    val committer: GiteaUser = GiteaUser(),
    val timestamp: String = "",
)

@Serializable
data class GiteaIssue(
    val id: Long = 0,
    val number: Long = 0,
    val title: String = "",
    val body: String = "",
    val state: String = "",
    @SerialName("html_url") val htmlUrl: String = "",
    val user: GiteaUser = GiteaUser(),
    val assignee: GiteaUser? = null,
    @SerialName("is_pull") val isPull: Boolean = false,
    val comments: Long = 0,
    @SerialName("created_at") val createdAt: String = "",
    @SerialName("updated_at") val updatedAt: String = "",
)

@Serializable
data class GiteaPullRequest(
    val id: Long = 0,
    val number: Long = 0,
    val title: String = "",
    val body: String = "",
    val state: String = "",
    val merged: Boolean = false,
    @SerialName("mergeable") val mergeable: Boolean? = null,
    @SerialName("html_url") val htmlUrl: String = "",
    val user: GiteaUser = GiteaUser(),
    @SerialName("head") val headBranch: GiteaBranchRef = GiteaBranchRef(),
    @SerialName("base") val baseBranch: GiteaBranchRef = GiteaBranchRef(),
    @SerialName("merged_by") val mergedBy: GiteaUser? = null,
    @SerialName("created_at") val createdAt: String = "",
    @SerialName("updated_at") val updatedAt: String = "",
)

@Serializable
data class GiteaBranchRef(
    val label: String = "",
    val ref: String = "",
    val sha: String = "",
    val repo: GiteaRepository = GiteaRepository(),
)

@Serializable
data class GiteaRelease(
    val id: Long = 0,
    @SerialName("tag_name") val tagName: String = "",
    @SerialName("target_commitish") val targetCommitish: String = "",
    val name: String = "",
    val body: String = "",
    val draft: Boolean = false,
    val prerelease: Boolean = false,
    val url: String = "",
    @SerialName("html_url") val htmlUrl: String = "",
    val author: GiteaUser = GiteaUser(),
    @SerialName("created_at") val createdAt: String = "",
)

@Serializable
data class GiteaSender(
    val id: Long = 0,
    val login: String = "",
    @SerialName("login_name") val loginName: String = "",
    @SerialName("full_name") val fullName: String = "",
    val email: String = "",
    @SerialName("avatar_url") val avatarUrl: String = "",
)

// --- Event payloads ---

@Serializable
data class PushPayload(
    val ref: String = "",
    val before: String = "",
    val after: String = "",
    @SerialName("compare_url") val compareUrl: String = "",
    val commits: List<GiteaCommit> = emptyList(),
    @SerialName("head_commit") val headCommit: GiteaCommit? = null,
    val pusher: GiteaUser? = null,
    val sender: GiteaUser = GiteaUser(),
    val repository: GiteaRepository = GiteaRepository(),
    @SerialName("total_commits") val totalCommits: Int = 0,
)

@Serializable
data class IssuesPayload(
    val action: String = "",
    val issue: GiteaIssue = GiteaIssue(),
    val sender: GiteaUser = GiteaUser(),
    val repository: GiteaRepository = GiteaRepository(),
)

@Serializable
data class PullRequestPayload(
    val action: String = "",
    val number: Long = 0,
    @SerialName("pull_request") val pullRequest: GiteaPullRequest = GiteaPullRequest(),
    val sender: GiteaUser = GiteaUser(),
    val repository: GiteaRepository = GiteaRepository(),
)

@Serializable
data class CreatePayload(
    val ref: String = "",
    @SerialName("ref_type") val refType: String = "",
    val sha: String = "",
    val sender: GiteaUser = GiteaUser(),
    val repository: GiteaRepository = GiteaRepository(),
)

@Serializable
data class DeletePayload(
    val ref: String = "",
    @SerialName("ref_type") val refType: String = "",
    val sha: String = "",
    val sender: GiteaUser = GiteaUser(),
    val repository: GiteaRepository = GiteaRepository(),
)

@Serializable
data class ReleasePayload(
    val action: String = "",
    val release: GiteaRelease = GiteaRelease(),
    val sender: GiteaUser = GiteaUser(),
    val repository: GiteaRepository = GiteaRepository(),
)

@Serializable
data class RepositoryPayload(
    val action: String = "",
    val repository: GiteaRepository = GiteaRepository(),
    val sender: GiteaUser = GiteaUser(),
)

@Serializable
data class ForkPayload(
    @SerialName("forkee") val forkedRepo: GiteaRepository = GiteaRepository(),
    val repository: GiteaRepository = GiteaRepository(),
    val sender: GiteaUser = GiteaUser(),
)

// --- Event type enum for routing ---

enum class GiteaEventType(val headerValue: String) {
    PUSH("push"),
    ISSUES("issues"),
    PULL_REQUEST("pull_request"),
    CREATE("create"),
    DELETE("delete"),
    RELEASE("release"),
    REPOSITORY("repository"),
    FORK("fork");

    companion object {
        fun fromHeader(value: String?): GiteaEventType? =
            entries.find { it.headerValue.equals(value, ignoreCase = true) }
    }
}
