<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" type="text/css" href="/static/css/style.css">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login to Burgercat</title>
</head>
<body>
    <div class="accountform">
        <br>
        <a href="/">back</a><br><br>
        <h1 id="text">Login to Burgercat</h1>
        <button onclick="authorize()">Log in with Burgerauth Account</button>
        <br><br>
        <button onclick="cuser_authorize()">Log in with Burgerauth Account (custom username)</button>
        <br><br>
        <button onclick="window.location.href = '/login'">Use legacy login</button>
    </div>
    
    <script>
        function getCookie(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) === ' ') c = c.substring(1, c.length);
                if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
            }
            return null;
        }

        // Configuration
        const clientId = 'Q7YTh3Tjt4ilOtOyVZjwxTfeei5HGnVC';
        const redirectUri = 'https://www.cta.social/oauth';
        const authorizationEndpoint = 'https://auth.hectabit.org/login';
        const tokenEndpoint = 'https://auth.hectabit.org/api/tokenauth';
        const userinfoEndpoint = 'https://auth.hectabit.org/userinfo'; // Added userinfo endpoint

        // Generate a random code verifier
        function generateCodeVerifier() {
            const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
            const length = 128;
            return Array.from(crypto.getRandomValues(new Uint8Array(length)))
                .map((x) => charset[x % charset.length])
                .join("");
        }

        // Create a code challenge from the code verifier using SHA-256
        async function createCodeChallenge(codeVerifier) {
            const buffer = new TextEncoder().encode(codeVerifier);
            const hashArrayBuffer = await crypto.subtle.digest('SHA-256', buffer);
            const hashBase64 = btoa(String.fromCharCode(...new Uint8Array(hashArrayBuffer)))
                .replace(/=/g, '')
                .replace(/\+/g, '-')
                .replace(/\//g, '_');
            return hashBase64;
        }


        function cuser_authorize() {
            document.cookie = "prefuser" + "=" + window.prompt("Choose your custom username (cannot be longer than 20 characters)") + "; expires=Session" + "; path=/" + "; samesite=Strict; secure=true;";
            authorize()
        }

        // Authorization function with PKCE
        function authorize() {
            const codeVerifier = generateCodeVerifier();
            localStorage.setItem('codeVerifier', codeVerifier); // Store code verifier
            createCodeChallenge(codeVerifier)
                .then((codeChallenge) => {
                    const authorizationUrl = `${authorizationEndpoint}?response_type=code&client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
                    window.location.href = authorizationUrl;
                })
                .catch((error) => {
                    console.error('Error generating code challenge:', error);
                });
        }

        // Parse the authorization code from the URL
        function parseCodeFromUrl() {
            const urlParams = new URLSearchParams(window.location.search);
            return urlParams.get('code');
        }

        // Exchange authorization code for access token
        async function exchangeCodeForToken(code) {
            const codeVerifier = localStorage.getItem('codeVerifier'); // Retrieve code verifier
            const formData = new URLSearchParams();
            formData.append('client_id', String(clientId));
            formData.append('code', String(code));
            formData.append('redirect_uri', String(redirectUri));
            formData.append('grant_type', 'authorization_code');
            formData.append('code_verifier', String(codeVerifier));

            const response = await fetch(tokenEndpoint, {
                method: 'POST',
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded"
                },
                body: formData
            });

            const data = await response.json();
            const accessToken = data.access_token;
            const idToken = data.id_token;

            // Request userinfo with id_token in bearer format
            fetch(userinfoEndpoint, {
                headers: {
                    "Authorization": `Bearer ${idToken}`
                }
            })
            .then((response) => {
                async function doStuff() {
                    if (response.status == 200) {
                        const userinfoData = await response.json();
                        console.log("User:", userinfoData.name)
                        console.log("Sub:", userinfoData.sub);
                        let preferreduser = userinfoData.name
                        if (getCookie("prefuser") != null) {
                            preferreduser = getCookie("prefuser")
                        }
                        document.getElementById("text").innerText = "Authenticating, " + userinfoData.name;
                        fetch("https://cat.hectabit.org/api/oauth", {
                            method: "POST",
                            headers: {
                                "Content-Type": "application/json"
                            },
                            body: JSON.stringify({
                                username: preferreduser,
                                access_token: data.access_token,
                                sub: userinfoData.sub
                            })
                        })
                        .then((response) => {
                            async function doStuff2() {
                                let key = await response.json()
                                if (response.status == 200) {
                                    document.cookie = "session_DO_NOT_SHARE" + "=" + (key["key"] || "") + "; expires=Session" + "; path=/" + "; samesite=Strict; secure=true;"
                                    window.location.replace("/")
                                } else if (response.status == 422) {
                                    document.getElementById("text").innerText = "Username taken. Migrate or choose a new custom username!"
                                } else {
                                    document.getElementById("text").innerText = "Failed: " + key["error"]
                                }
                            }
                            doStuff2()
                        });
                        localStorage.setItem("user", preferreduser)
                    } else {
                        document.getElementById("text").innerText = "Authentication failed"
                    }
                }
                doStuff()
            });
        }

        // Main function to handle OAuth2 flow
        async function main() {
            if (localStorage.getItem("user") !== null) {
                document.getElementById("text").innerText = "Welcome back, " + localStorage.getItem("user")
            }
            const code = parseCodeFromUrl();
            if (code) {
                await exchangeCodeForToken(code);
            }
        }

        // Call the main function on page load
        main();
    </script>
</body>
</html>