import os
import webbrowser
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs, urlencode, urlparse

from config.constants import AUTENTICATION_SUCCESS_MESSAGE, CLIENT_ID, REDIRECT_URI, SCOPES
from fivemserver.get_server_token import GetServerTokenForDiscord
from tools.http_client import ApiError, http_get, http_post

# Disable stderr output
os.environ['PYTHONWARNINGS'] = 'ignore'

OAUTH_AUTHORIZE_URL = "https://discord.com/api/oauth2/authorize"
OAUTH_TOKEN_URL = "https://discord.com/api/oauth2/token"
DISCORD_ME_URL = "https://discord.com/api/users/@me"
LOCAL_CALLBACK_HOST = "localhost"
LOCAL_CALLBACK_PORT = 5000

class OAuthCallbackHandler(BaseHTTPRequestHandler):
    code: str | None = None

    # Ajoute ceci pour empêcher le serveur d'écrire dans la console/stderr
    def log_message(self, format, *args):
        return  # Ne fait rien, donc pas de blocage sur stdout/stderr

    def do_GET(self):
        """
        callback pour discord auth
        """
        parsed_url = urlparse(self.path)
        if parsed_url.path != "/callback":
            self.send_error(404)
            return

        query_params = parse_qs(parsed_url.query)
        OAuthCallbackHandler.code = query_params.get("code", [None])[0]

        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(AUTENTICATION_SUCCESS_MESSAGE)

# return discord application id (client id)
def get_discord_client_id() -> str:
    """
    return discord application id
    """
    return CLIENT_ID

# return discord user id
def get_discord_user_id() -> tuple[str, str]:
    """
    Retourne l'id du compte discord de l'utilisateur via l'oauh discord.
    """

    # récupération des infos serveur la tanière
    session_id = GetServerTokenForDiscord.authenticate()
    client_secret = GetServerTokenForDiscord.get_token(session_id)

    auth_url = "https://discord.com/api/oauth2/authorize"
    params = {
        "client_id": CLIENT_ID,
        "redirect_uri": REDIRECT_URI,
        "response_type": "code",
        "scope": " ".join(SCOPES),
    }

    webbrowser.open(f"{auth_url}?{urlencode(params)}")

    server = HTTPServer((LOCAL_CALLBACK_HOST, LOCAL_CALLBACK_PORT), OAuthCallbackHandler)

    try:
        server.handle_request()
    finally:
        server.server_close()

    if not OAuthCallbackHandler.code:
        raise ApiError("OAuth échoué : aucun code de validation reçu.")

    try:
        token = http_post(
            OAUTH_TOKEN_URL,
            data={
                "client_id": CLIENT_ID,
                "client_secret": client_secret,
                "grant_type": "authorization_code",
                "code": OAuthCallbackHandler.code,
                "redirect_uri": REDIRECT_URI,
            },
            headers={"Content-Type": "application/x-www-form-urlencoded"},
        ).json()
    except ValueError as exc:
        raise ApiError("OAuth échoué : réponse JSON invalide lors de la récupération du token.",
                       url=OAUTH_TOKEN_URL) from exc

    access_token = token.get("access_token")
    if not access_token:
        raise ApiError("OAuth échoué : access_token manquant.", url=OAUTH_TOKEN_URL)

    try:
        user = http_get(
            DISCORD_ME_URL,
            headers={"Authorization": f"Bearer {access_token}"},
        ).json()
    except ValueError as exc:
        raise ApiError("OAuth échoué : réponse JSON invalide lors de la récupération du profil Discord.",
                       url=DISCORD_ME_URL) from exc

    user_id = user.get("id")
    if not user_id:
        raise ApiError("OAuth échoué : id utilisateur manquant.", url=DISCORD_ME_URL)

    return user_id, session_id
