from fastapi import FastAPI, HTTPException, security, Depends
import sqlalchemy.orm as orm
import services as services
import schemas as schemas
import models as models
from fastapi.middleware.cors import CORSMiddleware


app = FastAPI(title="TODO API",
              description='Todo App API using FastAPI, PostgreSQL and authentication support',
              version='0.0.1')

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
async def root():
    return {"Title": "Todo API",
            "Description": "Todo App API using FastAPI, PostgreSQL and authentication support",
            "Version": "0.0.1"}


# create user
@app.post("/api/users/")
async def create_user(user: schemas.userCreate,
                      db: orm.Session = Depends(services.get_db)):

    db_user = await services.get_user_by_email(email=user.email.lower(), db=db)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    # Await the create_user function
    user = await services.create_user(user=user, db=db)
    token = await services.create_token(user=user)
    return token


@app.post("/api/token/")
async def generate_token(form_data: security.OAuth2PasswordRequestForm = Depends(),
                         db: orm.Session = Depends(services.get_db)):

    user = await services.authenticate_user(form_data.username.lower(), form_data.password, db=db)
    if not user:
        raise HTTPException(
            status_code=401, detail="Incorrect email or password")
    token = await services.create_token(user=user)
    return {
        "access_token": token['access_token'],
        "first_name": user.first_name,
        "last_name": user.last_name,
    }


@app.get('/api/users/me', response_model=schemas.User)
async def get_user(user: schemas.User = Depends(services.get_current_user)):
    return user


@app.post("/api/users/todo")
async def create_todo(todo: schemas.TodoCreate, user: schemas.User = Depends(services.get_current_user), db: orm.Session = Depends(services.get_db)):
    return await services.create_todo(user=user, todo=todo, db=db)


@app.get("/api/users/todo")
async def get_todos(user: schemas.User = Depends(services.get_current_user), db: orm.Session = Depends(services.get_db)):
    return await services.get_todos(user=user, db=db)


@app.put("/api/users/todo/{todo_id}")
async def update_todo(todo_id: int,
                      todo: schemas.TodoCreate,
                      user: schemas.User = Depends(services.get_current_user),
                      db: orm.Session = Depends(services.get_db)):
    return {
        "todo": await services.update_todo(user=user, db=db, todo=todo, todo_id=todo_id),
        "message": "Todo updated successfully"
    }


@app.delete("/api/users/todo/{todo_id}")
async def delete_todo(todo_id: int,
                      user: schemas.User = Depends(services.get_current_user),
                      db: orm.Session = Depends(services.get_db)):
    return {
        "todo": await services.delete_todo(user=user, db=db, todo_id=todo_id),
        "message": "Todo deleted successfully"
    }


@app.get("/api/users/todo/today")
async def get_today_todos(user: schemas.User = Depends(services.get_current_user), db: orm.Session = Depends(services.get_db)):
    return await services.get_today_todos(user=user, db=db)


@app.get("/api/users/todo/overdue")
async def get_overdue_todos(user: schemas.User = Depends(services.get_current_user), db: orm.Session = Depends(services.get_db)):
    return await services.get_overdue_todos(user=user, db=db)


@app.get("/api/users/todo/upcoming")
async def get_upcoming_todos(user: schemas.User = Depends(services.get_current_user), db: orm.Session = Depends(services.get_db)):
    return await services.get_upcoming_todos(user=user, db=db)

@app.get("/api/users/todo/completed")
async def get_completed_todos(user: schemas.User = Depends(services.get_current_user), db: orm.Session = Depends(services.get_db)):
    return await services.get_completed_todos(user=user, db=db)