import { Elysia } from "elysia"
import {
    getAuthorizationUrl,
    exchangeCodeForTokens,
    fetchUserIdentity,
    createOrUpdateUser,
    createSession,
    deleteSession,
    getUserFromSession
} from "../lib/auth"
import { config } from "../config"
import { getUserScrapsBalance } from "../lib/scraps"

const FRONTEND_URL = config.frontendUrl

const authRoutes = new Elysia({ prefix: "/auth" })

// GET /auth/login - Redirect to Hack Club Auth
authRoutes.get("/login", ({ redirect }) => {
    console.log("[AUTH] Login initiated")
    return redirect(getAuthorizationUrl())
})

// GET /auth/callback - Handle OIDC callback
authRoutes.get("/callback", async ({ query, redirect, cookie }) => {
    console.log("[AUTH] Callback received")
    const code = query.code as string | undefined

    if (!code) {
        console.log("[AUTH] Callback error: no code provided")
        return redirect(`${FRONTEND_URL}/auth/error?reason=auth-failed`)
    }

    try {
        const tokens = await exchangeCodeForTokens(code)
        if (!tokens) {
            console.log("[AUTH] Callback error: token exchange failed")
            return redirect(`${FRONTEND_URL}/auth/error?reason=auth-failed`)
        }

        const meResponse = await fetchUserIdentity(tokens.access_token)
        if (!meResponse) {
            console.log("[AUTH] Callback error: failed to fetch user identity")
            return redirect(`${FRONTEND_URL}/auth/error?reason=auth-failed`)
        }

        const { identity } = meResponse
        console.log("[AUTH] Identity received:", {
            id: identity.id,
            email: identity.primary_email,
            slackId: identity.slack_id,
            yswsEligible: identity.ysws_eligible,
            verificationStatus: identity.verification_status
        })

        const user = await createOrUpdateUser(identity, tokens)
        
        if (user.role === 'banned') {
            console.log("[AUTH] Banned user attempted login:", { userId: user.id, username: user.username })
            return redirect('https://fraud.land')
        }

        const sessionToken = await createSession(user.id)
        console.log("[AUTH] User authenticated successfully:", { userId: user.id, username: user.username })

        cookie.session.set({
            value: sessionToken,
            httpOnly: true,
            secure: !config.isDev,
            sameSite: "lax",
            maxAge: 7 * 24 * 60 * 60,
            path: "/"
        })

        return redirect(`${FRONTEND_URL}/dashboard`)
    } catch (error) {
        const msg = error instanceof Error ? error.message : "unknown"
        console.log("[AUTH] Callback error:", msg, error)
        if (msg === "not-eligible") {
            return redirect(`${FRONTEND_URL}/auth/error?reason=not-eligible`)
        }
        return redirect(`${FRONTEND_URL}/auth/error?reason=auth-failed`)
    }
})

// GET /auth/me - Get current user
authRoutes.get("/me", async ({ headers }) => {
    const user = await getUserFromSession(headers as Record<string, string>)
    console.log("[AUTH] /me check:", user ? { userId: user.id, username: user.username } : "no session")
    if (!user) return { user: null }
    if (user.role === 'banned') {
        return { user: null, banned: true }
    }
    const scrapsBalance = await getUserScrapsBalance(user.id)
    return {
        user: {
            id: user.id,
            username: user.username,
            email: user.email,
            avatar: user.avatar,
            slackId: user.slackId,
            scraps: scrapsBalance.balance,
            role: user.role,
            tutorialCompleted: user.tutorialCompleted
        }
    }
})

// POST /auth/logout
authRoutes.post("/logout", async ({ cookie }) => {
    console.log("[AUTH] Logout requested")
    const token = cookie.session.value as string | undefined
    if (token) {
        await deleteSession(token)
        cookie.session.remove()
    }
    return { success: true }
})

export default authRoutes
