from fastapi import APIRouter, Depends, HTTPException, Query, Response
from typing import List, Optional
import logging
import pydantic

from ..db_engine import db, Division, Team, model_to_dict, chunked, fn
from ..dependencies import oauth2_scheme, valid_token, PRIVATE_IN_SCHEMA, handle_db_errors

logger = logging.getLogger('discord_app')

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


class DivisionModel(pydantic.BaseModel):
    division_name: str
    division_abbrev: str
    league_name: Optional[str]
    league_abbrev: Optional[str]
    season: int = 0


@router.get('')
@handle_db_errors
async def get_divisions(
        season: int, div_name: Optional[str] = None, div_abbrev: Optional[str] = None, lg_name: Optional[str] = None,
        lg_abbrev: Optional[str] = None):
    all_divisions = Division.select().where(Division.season == season)

    if div_name is not None:
        all_divisions = all_divisions.where(Division.division_name == div_name)
    if div_abbrev is not None:
        all_divisions = all_divisions.where(Division.division_abbrev == div_abbrev)
    if lg_name is not None:
        all_divisions = all_divisions.where(Division.league_name == lg_name)
    if lg_abbrev is not None:
        all_divisions = all_divisions.where(Division.league_abbrev == lg_abbrev)

    return_div = {
        'count': all_divisions.count(),
        'divisions': [model_to_dict(x) for x in all_divisions]
    }
    db.close()
    return return_div


@router.get('/{division_id}')
@handle_db_errors
async def get_one_division(division_id: int):
    this_div = Division.get_or_none(Division.id == division_id)
    if this_div is None:
        db.close()
        raise HTTPException(status_code=404, detail=f'Division ID {division_id} not found')

    r_div = model_to_dict(this_div)
    db.close()
    return r_div


@router.patch('/{division_id}', include_in_schema=PRIVATE_IN_SCHEMA)
@handle_db_errors
async def patch_division(
        division_id: int, div_name: Optional[str] = None, div_abbrev: Optional[str] = None,
        lg_name: Optional[str] = None, lg_abbrev: Optional[str] = None, token: str = Depends(oauth2_scheme)):
    if not valid_token(token):
        logger.warning(f'patch_division - Bad Token: {token}')
        raise HTTPException(status_code=401, detail='Unauthorized')

    this_div = Division.get_or_none(Division.id == division_id)
    if this_div is None:
        db.close()
        raise HTTPException(status_code=404, detail=f'Division ID {division_id} not found')

    if div_name is not None:
        this_div.division_name = div_name
    if div_abbrev is not None:
        this_div.division_abbrev = div_abbrev
    if lg_name is not None:
        this_div.league_name = lg_name
    if lg_abbrev is not None:
        this_div.league_abbrev = lg_abbrev

    if this_div.save() == 1:
        r_division = model_to_dict(this_div)
        db.close()
        return r_division
    else:
        db.close()
        raise HTTPException(status_code=500, detail=f'Unable to patch division {division_id}')


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

    this_division = Division(**new_division.dict())

    if this_division.save() == 1:
        r_division = model_to_dict(this_division)
        db.close()
        return r_division
    else:
        db.close()
        raise HTTPException(status_code=500, detail=f'Unable to post division')


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

    this_div = Division.get_or_none(Division.id == division_id)
    if this_div is None:
        db.close()
        raise HTTPException(status_code=404, detail=f'Division ID {division_id} not found')

    count = this_div.delete_instance()
    db.close()

    if count == 1:
        return f'Division {division_id} has been deleted'
    else:
        raise HTTPException(status_code=500, detail=f'Division {division_id} could not be deleted')


