"""
OAuth authentication routes.
"""
from fastapi import APIRouter, HTTPException, Response
from pydantic import BaseModel
import secrets
import structlog
from app.core.oauth import google_oauth, github_oauth
from app.core.auth import jwt_auth
from app.db.postgres import db
import uuid

logger = structlog.get_logger(__name__)

router = APIRouter()

# In-memory state storage (use Redis in production)
oauth_states = {}


class OAuthCallbackRequest(BaseModel):
    code: str
    state: str


class LinkLicenseRequest(BaseModel):
    license_key: str


@router.get("/google/authorize")
async def google_authorize():
    """Initiate Google OAuth flow."""
    state = secrets.token_urlsafe(32)
    oauth_states[state] = "google"
    url = google_oauth.get_authorization_url(state)
    return {"url": url}


@router.get("/github/authorize")
async def github_authorize():
    """Initiate GitHub OAuth flow."""
    state = secrets.token_urlsafe(32)
    oauth_states[state] = "github"
    url = github_oauth.get_authorization_url(state)
    return {"url": url}


@router.post("/google/callback")
async def google_callback(request: OAuthCallbackRequest):
    """Handle Google OAuth callback."""
    # Verify state
    if request.state not in oauth_states:
        raise HTTPException(status_code=400, detail="Invalid state")
        
    # Get user info from Google
    user_info = await google_oauth.get_user_info(request.code)
    if not user_info:
        raise HTTPException(status_code=400, detail="Failed to get user info")
        
    # Check if user exists
    user = await db.fetchrow(
        "SELECT * FROM users WHERE google_id = $1 OR email = $2",
        user_info['provider_id'],
        user_info['email']
    )
    
    if user:
        # Update existing user
        await db.execute(
            "UPDATE users SET google_id = $1, name = $2, avatar_url = $3 WHERE id = $4",
            user_info['provider_id'],
            user_info['name'],
            user_info['avatar_url'],
            user['id']
        )
        user_id = user['id']
        tier = user['tier']
        license_key = user['license_key']
    else:
        # Create new free tier user
        user_id = str(uuid.uuid4())
        await db.execute(
            """
            INSERT INTO users (id, email, name, avatar_url, google_id, tier)
            VALUES ($1, $2, $3, $4, $5, 'free')
            """,
            user_id,
            user_info['email'],
            user_info['name'],
            user_info['avatar_url'],
            user_info['provider_id']
        )
        tier = "free"
        license_key = None
        
    # Create JWT token
    token = jwt_auth.create_token(
        license_key=license_key or user_id,
        email=user_info['email'],
        tier=tier
    )
    
    refresh_token = jwt_auth.create_refresh_token(
        license_key=license_key or user_id,
        email=user_info['email']
    )
    
    # Clean up state
    del oauth_states[request.state]
    
    return {
        "token": token,
        "refresh_token": refresh_token,
        "tier": tier,
        "email": user_info['email'],
        "name": user_info['name'],
        "avatar_url": user_info['avatar_url'],
        "needs_license": license_key is None and tier == "free"
    }


@router.post("/github/callback")
async def github_callback(request: OAuthCallbackRequest):
    """Handle GitHub OAuth callback."""
    # Verify state
    if request.state not in oauth_states:
        raise HTTPException(status_code=400, detail="Invalid state")
        
    # Get user info from GitHub
    user_info = await github_oauth.get_user_info(request.code)
    if not user_info:
        raise HTTPException(status_code=400, detail="Failed to get user info")
        
    # Check if user exists
    user = await db.fetchrow(
        "SELECT * FROM users WHERE github_id = $1 OR email = $2",
        user_info['provider_id'],
        user_info['email']
    )
    
    if user:
        # Update existing user
        await db.execute(
            "UPDATE users SET github_id = $1, name = $2, avatar_url = $3 WHERE id = $4",
            user_info['provider_id'],
            user_info['name'],
            user_info['avatar_url'],
            user['id']
        )
        user_id = user['id']
        tier = user['tier']
        license_key = user['license_key']
    else:
        # Create new free tier user
        user_id = str(uuid.uuid4())
        await db.execute(
            """
            INSERT INTO users (id, email, name, avatar_url, github_id, tier)
            VALUES ($1, $2, $3, $4, $5, 'free')
            """,
            user_id,
            user_info['email'],
            user_info['name'],
            user_info['avatar_url'],
            user_info['provider_id']
        )
        tier = "free"
        license_key = None
        
    # Create JWT token
    token = jwt_auth.create_token(
        license_key=license_key or user_id,
        email=user_info['email'],
        tier=tier
    )
    
    refresh_token = jwt_auth.create_refresh_token(
        license_key=license_key or user_id,
        email=user_info['email']
    )
    
    # Clean up state
    del oauth_states[request.state]
    
    return {
        "token": token,
        "refresh_token": refresh_token,
        "tier": tier,
        "email": user_info['email'],
        "name": user_info['name'],
        "avatar_url": user_info['avatar_url'],
        "needs_license": license_key is None and tier == "free"
    }


@router.post("/link-license")
async def link_license(request: LinkLicenseRequest, current_user: dict = Depends(get_current_user)):
    """Link a license key to the current OAuth user."""
    from app.api.deps import get_current_user
    from fastapi import Depends
    
    # Verify license exists and is active
    license_row = await db.fetchrow(
        "SELECT * FROM licenses WHERE license_key = $1 AND status = 'active'",
        request.license_key
    )
    
    if not license_row:
        raise HTTPException(status_code=404, detail="Invalid or inactive license key")
        
    # Link license to user
    await db.execute(
        "UPDATE users SET license_key = $1, tier = $2 WHERE email = $3",
        request.license_key,
        license_row['tier'],
        current_user['email']
    )
    
    # Return new token with updated tier
    token = jwt_auth.create_token(
        license_key=request.license_key,
        email=current_user['email'],
        tier=license_row['tier']
    )
    
    return {"message": "License linked successfully", "token": token, "tier": license_row['tier']}
