/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.routes

import de.steamwar.ResponseError
import de.steamwar.plugins.SWUserSession
import de.steamwar.sql.SteamwarUser
import io.ktor.client.*
import io.ktor.client.engine.java.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive

@Serializable
data class UsernamePassword(val name: String, val password: String, val keepLoggedIn: Boolean = false)

fun Route.configureAuth() {
    route("/auth") {
        val client = HttpClient(Java) {
            install(ContentNegotiation) {
                json()
            }
        }

        post {
            val request = call.receive<UsernamePassword>()

            SteamwarUser.clear()
            val user = SteamwarUser.get(request.name)
            val valid = user?.verifyPassword(request.password)
                ?: false

            if (!valid) {
                call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid username or password", "invalid"))
                return@post
            }

            call.sessions.set(SWUserSession(user.getId()))
            call.respond(ResponseUser(user))
        }

        delete {
            call.sessions.clear<SWUserSession>()
            call.respond(HttpStatusCode.NoContent)
        }

        route("/discord") {
            post {
                val token = call.receiveText()

                val res = client.get("https://discord.com/api/v10/oauth2/@me") {
                    headers {
                        append("Authorization", "Bearer $token")
                    }
                }
                val resJson = Json.parseToJsonElement(res.bodyAsText()).jsonObject
                val discordId = resJson["user"]?.jsonObject["id"]?.jsonPrimitive?.content

                if (discordId == null) {
                    call.respond(HttpStatusCode.Forbidden, ResponseError("Invalid Discord token", "invalid"))
                    return@post
                }

                SteamwarUser.clear()
                val user = SteamwarUser.get(discordId.toLong())

                if (user == null) {
                    call.respond(HttpStatusCode.Forbidden, ResponseError("Discord account not linked", "not_linked"))
                    return@post
                }

                call.sessions.set(SWUserSession(user.getId()))
                call.respond(ResponseUser(user))
            }
        }
    }
}