from fastapi import APIRouter, Depends, HTTPException
from typing import Optional
import logging
import pydantic

from ..db_engine import db, Current, model_to_dict
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors

logger = logging.getLogger('discord_app')

router = APIRouter(
    prefix='/api/v3/current',
    tags=['current']
)


class CurrentModel(pydantic.BaseModel):
    week: Optional[int] = 0
    freeze: Optional[bool] = False
    season: int
    transcount: Optional[int] = 0
    bstatcount: Optional[int] = 0
    pstatcount: Optional[int] = 0
    bet_week: Optional[int] = 0
    trade_deadline: int
    pick_trade_start: int = 69
    pick_trade_end: int = 420
    playoffs_begin: int
    injury_count: Optional[int] = 0


@router.get('')
@handle_db_errors
async def get_current(season: Optional[int] = None):
    if season is not None:
        current = Current.get_or_none(season=season)
    else:
        current = Current.latest()

    if current is not None:
        r_curr = model_to_dict(current)
        db.close()
        return r_curr
    else:
        return None


@router.patch('/{current_id}', include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors
async def patch_current(
        current_id: int, season: Optional[int] = None, week: Optional[int] = None, freeze: Optional[bool] = None,
        transcount: Optional[int] = None, bstatcount: Optional[int] = None, pstatcount: Optional[int] = None,
        bet_week: Optional[int] = None, trade_deadline: Optional[int] = None, pick_trade_start: Optional[int] = None,
        pick_trade_end: Optional[int] = None, injury_count: Optional[int] = None, token: str = Depends(oauth2_scheme)):
    if not valid_token(token):
        logger.warning(f'patch_current - Bad Token: {token}')
        raise HTTPException(status_code=401, detail='Unauthorized')

    try:
        current = Current.get_by_id(current_id)
    except Exception as e:
        raise HTTPException(status_code=404, detail=f'Current id {current_id} not found')

    if week is not None:
        current.week = week
    if season is not None:
        current.season = season
    if freeze is not None:
        current.freeze = freeze
    if transcount is not None:
        current.transcount = transcount
    if bstatcount is not None:
        current.bstatcount = bstatcount
    if pstatcount is not None:
        current.pstatcount = pstatcount
    if bet_week is not None:
        current.bet_week = bet_week
    if trade_deadline is not None:
        current.trade_deadline = trade_deadline
    if pick_trade_start is not None:
        current.pick_trade_start = pick_trade_start
    if pick_trade_end is not None:
        current.pick_trade_end = pick_trade_end
    if injury_count is not None:
        current.injury_count = injury_count

    if current.save():
        r_curr = model_to_dict(current)
        db.close()
        return r_curr
    else:
        db.close()
        raise HTTPException(status_code=500, detail=f'Unable to patch current {current_id}')


@router.post('', include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors
async def post_current(new_current: CurrentModel, token: str = Depends(oauth2_scheme)):
    if not valid_token(token):
        logger.warning(f'patch_current - Bad Token: {token}')
        raise HTTPException(status_code=401, detail='Unauthorized')

    this_current = Current(**new_current.dict())

    if this_current.save():
        r_curr = model_to_dict(this_current)
        db.close()
        return r_curr
    else:
        db.close()
        raise HTTPException(status_code=500, detail=f'Unable to post season {new_current.season} current')


@router.delete('/{current_id}', include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors
async def delete_current(current_id: int, token: str = Depends(oauth2_scheme)):
    if not valid_token(token):
        logger.warning(f'patch_current - Bad Token: {token}')
        raise HTTPException(status_code=401, detail='Unauthorized')

    if Current.delete_by_id(current_id) == 1:
        return f'Deleted current ID {current_id}'

    raise HTTPException(status_code=500, detail=f'Unable to delete current {current_id}')
