from fastapi import APIRouter, Cookie, HTTPException, Depends
from fastapi.responses import RedirectResponse
from sqlalchemy.orm import Session
from typing import Optional, Union
from requests import get, post
from urllib.parse import urlencode
from dotenv import load_dotenv
import os

from db.database import get_db
from db import crud

# load environment variables
load_dotenv("../.env")

router = APIRouter(prefix="/api/auth", tags=["auth"])


@router.get("/")
async def whoami(connect_id: str = Cookie(...), db: Session = Depends(get_db)):
    user = crud.get_user(connect_id, db)
    return user.username


@router.get("/login")
async def login(code: Optional[str] = None, state: Optional[str] = None, connect_id: Union[str, None] = Cookie(default=None), db: Session = Depends(get_db)):

    if not code:
        init_user = crud.init_user(db)
        params = urlencode({
            "client_id": os.getenv("CLIENT_ID"),
            "redirect_uri": f"{os.getenv('API_ROOT')}/auth/login",
            "response_type": "code",
            "state": init_user.state,
            "scope": "default"})
        response = RedirectResponse(f"{os.getenv('AUTH_ROOT')}/oauth/authorize?{params}")
        response.set_cookie(key="connect_id", value=init_user.cookie)
        return response

    if not connect_id or not state:
        raise HTTPException(status_code=403, detail="Cookie Invalid")
    user = crud.get_user(connect_id, db)
    if not user:
        raise HTTPException(status_code=599, detail="Timeout error")
    if user.state != state:
        raise HTTPException(status_code=403, detail="State Invalid")
    crud.delete_state(user, db)

    headers = {"content-type": "application/x-www-form-urlencoded"}
    data = {
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": f"{os.getenv('API_ROOT')}/auth/login",
        "client_id": os.getenv("CLIENT_ID"),
        "client_secret": os.getenv("CLIENT_SECRET"),
    }

    token_response = post(
        f"{os.getenv('AUTH_ROOT')}/oauth/token",
        data=data,
        headers=headers
    )

    access_token = token_response.json()["access_token"]
    user_info = get(
        f"{os.getenv('AUTH_ROOT')}/api/user/show/me",
        headers={"Authorization": f"Bearer {access_token}"}
    )

    user = crud.update_user(user, user_info.json(), db)
    return RedirectResponse(f"{os.getenv('WEB_ROOT')}?connected=true")


@router.get("/logout")
async def delete_session(connect_id: str = Cookie(...), db: Session = Depends(get_db)):
    response = RedirectResponse(f"{os.getenv('AUTH_ROOT')}/logout?{urlencode({'redirect_logout': os.getenv('WEB_ROOT')})}")
    try:
        response.delete_cookie(key="connect_id")
        crud.end_session(connect_id, db)
    finally:
        return response
