from typing import Union

from flask import request
from flask_restful import Resource

from exceptions import InvalidRequestError
from models import Scoring
from utils import flask_response, rank, sort


class ScoringRoute(Resource):
    @flask_response
    def get(self, side_of_ball: str) -> Union[Scoring, list[Scoring]]:
        """
        GET request to get scoring offense or defense for the given years.
        If team is provided only get scoring data for that team.

        Args:
            side_of_ball (str): Offense or defense

        Returns:
          Union[Scoring, list[Scoring]]: Scoring data for all teams
              or only scoring data for one team
        """
        if side_of_ball not in ['offense', 'defense']:
            raise InvalidRequestError(
                "Side of ball must be either 'offense' or 'defense'")

        sort_attr = request.args.get('sort', 'points_per_game')
        secondary_attr, secondary_reverse = secondary_sort(
            attr=sort_attr, side_of_ball=side_of_ball)

        try:
            start_year = int(request.args['start_year'])
        except KeyError:
            raise InvalidRequestError(
                'Start year is a required query parameter')
        except ValueError:
            raise InvalidRequestError(
                'Query parameter start year must be an integer')

        end_year = request.args.get('end_year')
        team = request.args.get('team')

        if end_year is not None:
            try:
                end_year = int(end_year)
            except ValueError:
                raise InvalidRequestError(
                    'Query parameter end year must be an integer')

        scoring = Scoring.get_scoring(
            side_of_ball=side_of_ball,
            start_year=start_year,
            end_year=end_year,
            team=team
        )

        if isinstance(scoring, Scoring):
            return scoring

        attrs = [secondary_attr, sort_attr]
        reverses = [secondary_reverse, side_of_ball == 'offense']

        scoring = sort(data=scoring, attrs=attrs, reverses=reverses)
        return rank(data=scoring, attr=sort_attr)


def secondary_sort(attr: str, side_of_ball: str) -> tuple:
    """
    Determine the secondary sort attribute and order when the
    primary sort attribute has the same value.

    Args:
        attr (str): The primary sort attribute
        side_of_ball (str): Offense or defense

    Returns:
        tuple: Secondary sort attribute and sort order
    """
    if attr == 'points_per_game':
        secondary_attr = 'games'

    elif attr in ['points', 'relative_points_per_game']:
        secondary_attr = 'points_per_game'

    else:
        secondary_attr = attr

    return secondary_attr, side_of_ball == 'offense'

[((29, 20, 29, 63), 'flask.request.args.get', 'request.args.get', ({(29, 37, 29, 43): '"""sort"""', (29, 45, 29, 62): '"""points_per_game"""'}, {}), "('sort', 'points_per_game')", False, 'from flask import request\n'), ((42, 19, 42, 47), 'flask.request.args.get', 'request.args.get', ({(42, 36, 42, 46): '"""end_year"""'}, {}), "('end_year')", False, 'from flask import request\n'), ((43, 15, 43, 39), 'flask.request.args.get', 'request.args.get', ({(43, 32, 43, 38): '"""team"""'}, {}), "('team')", False, 'from flask import request\n'), ((52, 18, 57, 9), 'models.Scoring.get_scoring', 'Scoring.get_scoring', (), '', False, 'from models import Scoring\n'), ((65, 18, 65, 68), 'utils.sort', 'sort', (), '', False, 'from utils import flask_response, rank, sort\n'), ((66, 15, 66, 49), 'utils.rank', 'rank', (), '', False, 'from utils import flask_response, rank, sort\n'), ((26, 18, 27, 69), 'exceptions.InvalidRequestError', 'InvalidRequestError', ({(27, 16, 27, 68): '"""Side of ball must be either \'offense\' or \'defense\'"""'}, {}), '("Side of ball must be either \'offense\' or \'defense\'")', False, 'from exceptions import InvalidRequestError\n'), ((36, 18, 37, 59), 'exceptions.InvalidRequestError', 'InvalidRequestError', ({(37, 16, 37, 58): '"""Start year is a required query parameter"""'}, {}), "('Start year is a required query parameter')", False, 'from exceptions import InvalidRequestError\n'), ((39, 18, 40, 64), 'exceptions.InvalidRequestError', 'InvalidRequestError', ({(40, 16, 40, 63): '"""Query parameter start year must be an integer"""'}, {}), "('Query parameter start year must be an integer')", False, 'from exceptions import InvalidRequestError\n'), ((49, 22, 50, 66), 'exceptions.InvalidRequestError', 'InvalidRequestError', ({(50, 20, 50, 65): '"""Query parameter end year must be an integer"""'}, {}), "('Query parameter end year must be an integer')", False, 'from exceptions import InvalidRequestError\n')]