import requests
import json


class CBSSportsRequests(object):
    def __init__(self, pool_id: str = ''):
        self.ENDPOINT = "https://picks.cbssports.com/graphql"
        self.pool_id = pool_id

    def post(self, operation_name: str = '', variables: dict = None, query: str = ''):
        payload = {
            "operationName": operation_name,
            "variables": variables,
            "query": query
        }
        with requests.Session() as session:
            r = session.post(self.ENDPOINT, json=payload)
            return r.json()

    def get(self, operation_name: str = '', variables: dict = None, extensions: dict = None):
        parameters = {
            "operationName": operation_name,
            "variables": json.dumps(variables),
            "extensions": json.dumps(extensions)
        }
        with requests.Session() as session:
            r = session.get(self.ENDPOINT, params=parameters)
            return r.json()

    def bracket_state(self):
        operation_name = "CentralBracketsState"
        variables = {}
        query = """
          query CentralBracketsState {
            mensBracketState: bracketState(gameInstanceUid: "cbs-ncaab-tournament-challenge") {
              id
              isPreTournament
              locksAt
              isLocked
            }
            womensBracketState: bracketState(gameInstanceUid: "cbs-ncaaw-tournament-challenge") {
              id
              isPreTournament
              locksAt
              isLocked
            }
          }
        """
        return self.post(operation_name, variables, query)

    def cbs_teams(self):
        operation_name = "CentralTeamsQuery"
        variables = {
            "sportTypes": ["NCAAB"],
            "subsection": None
        }
        query = """
        query CentralTeamsQuery($sportTypes: [GameSportTypeEnumType!], $subsection: GameSubsectionEnumType) {
          teams(sportTypes: $sportTypes, subsection: $subsection) {
            id
            abbrev
            location
            nickName
            shortName
            sportType
            colorHexDex
            colorPrimaryHex
            colorSecondaryHex
            conferenceAbbrev
            cbsTeamId
            wins
            losses
            ties
            imageUrl
            mediumName
          }
        }
        """
        return self.post(operation_name, variables, query)

    def entry(self, entry_id: str):
        operation_name = "EntryDetailsQuery"
        variables = {
            "entryId": entry_id,
            "periodId": "current",
            "skipPoolData": False
        }
        query = """
        query EntryDetailsQuery($entryId: ID!, $periodId: ID!, $skipPoolData: Boolean = false) {
          entry(id: $entryId) {
          ...EntryDetailsFragment
          }
        }
        
        fragment EntryDetailsFragment on Entry {
          id
          name
          gameInstanceUid
          isMine
          url
          avatarUrl
          hideEmail
          roles
          memberId
          hidePicksOnboarding
          hasSeenNativeAppPromo
          totalPicksCount
          maxPicksCount
          poolRank
          correctPicks
          fantasyPoints
          maxPoints
          noMessageBoardNotification
          reinvitedPassword
          currentSeasonEntryId
          hasAutogeneratedName
          lastDismissedReactivateSeasonId
          canDeleteEntry
          canLeavePool
          userId
          isOfflineEntry
          userInfo {
            id
            email
          }
          championTeam {
            id
            cbsTeamId
          }
          pool @skip(if: $skipPoolData) {
            id
            name
            url
            season {
              id
              challengePoolId
            }
          }
          needsToMakePicks(period: { periodId: $periodId })
          periodPoint(period: { periodId: $periodId }, excludeUnranked: false) {
          ...EntryGlanceQueryPeriodPointFragment
          }
          picks(period: { periodId: $periodId }) {
            id
            slotId
            itemId
            periodId
            additionalPoints
            spreadForItem
          }
          tiebreakerAnswers(period: { periodId: $periodId }) {
            id
            tiebreakerQuestionId
            value
          }
        }
        
        fragment EntryGlanceQueryPeriodPointFragment on PeriodPoint {
          id
          periodId
          poolRank
          percentile
          fantasyPoints
          picksCount
          maxPicksCount
        }
        """
        return self.post(operation_name, variables, query)

    def pool_details(self):
        operation_name = "CentralPoolDetailsQuery"
        variables = {"poolId": self.pool_id}
        query = """
        query CentralPoolDetailsQuery($poolId: ID!) {
          pool(id: $poolId) {
          ...CentralPoolDetailsFragment
          }
        }

        fragment CentralPoolDetailsFragment on Pool {
          id
          name
          slogan
          url
          password
          poolSettings {
            ...PoolSettingsFragment
          }
          gameInstanceUid
          currentSeasonPoolId
          currentSeasonPoolUrl
          parentPoolId
          entriesCount
          membersCount
          isPublic
          usesMagicLink
          avatarUrl
          canAddEntry
          inviteUrl
          season {
            ...CentralSeasonFragment
          }
          hasSeenManagerWelcomeBackModal
          inviteAllEmailSent
          helpDeskUrl
          canViewEarly
          hasSeenNewSettingPopover
        }

        fragment CentralSeasonFragment on Season {
          id
          season
          year
          masterProductId
          challengePoolSlug
          challengePoolId
          productAbbrev
          isArchived
          isCurrent
          svgLogoFullPath
          customCopy
          appPromoUrl
          rulesUrl
          hasPrizes
          seasonSignupSponsorDataForm {
            id
            name
            inputFields {
              id
              type
              label
              name
              extraHtml
            }
          }
          whenToWatch {
            id
            periodName
            dates
          }
          gameInstance {
            id
            uid
            client
          }
        }

        fragment PoolSettingsFragment on PoolSettings {
          id
          maxEntriesPerUser
          mainTiebreaker
          roundBonuses
          roundModifiers
          includeMessageBoard
          openInvites
        }
        """
        return self.post(operation_name, variables, query)

    def pool_period(self):
        operation_name = "PoolPeriodQuery"
        variables = {
            "gameInstanceUid": "cbs-ncaab-tournament-manager",
            "periodId": "current",
            "order": None,
            "year": None,
            "poolId": self.pool_id
        }
        extensions = {
            "persistedQuery": {
                "version": 1,
                "sha256Hash": "bd4dd3122d072d332e7cd9143d0d29dcbde35798a79cea4703319efa42a95e04"
            }
        }
        return self.get(operation_name, variables, extensions)

    def pool_standings(self):
        operation_name = "PoolSeasonStandingsQuery"
        variables = {
            "gameInstanceUid": "cbs-ncaab-tournament-manager",
            "poolId": self.pool_id,
            "first": 50,
            "includedEntryIds": None,
            "orderBy": "OVERALL_RANK",
            "sortingOrder": "ASC",
            "after": None,
            "skipAncestorPools": False,
            "skipPeriodPoints": False,
            "skipCheckForIncompleteEntries": True
        }
        query = """
          query PoolSeasonStandingsQuery(
            $gameInstanceUid: String!
            $poolId: ID!
            $first: Int!
            $includedEntryIds: [ID!]
            $orderBy: EntryOrderByType
            $sortingOrder: SortingOrderByType
            $after: ID
            $skipAncestorPools: Boolean = false
            $skipPeriodPoints: Boolean = false
            $skipCheckForIncompleteEntries: Boolean = true
          ) {
            gameInstance(game: { uid: $gameInstanceUid }) {
              id
              pool(id: $poolId) {
                id
                name
                url
                entriesCount
                entriesWithPicksCount
                hasIncompleteEntries @skip(if: $skipCheckForIncompleteEntries)
                entries(first: $first, after: $after, includedEntryIds: $includedEntryIds, orderBy: $orderBy, sortingOrder: $sortingOrder) {
                  pageInfo {
                    hasNextPage
                    startCursor
                    endCursor
                  }
                  edges {
                    cursor
                    node {
                      id
                      name
                      fantasyPoints
                      poolRank
                      url
                      hasGameDataOnly
                      championTeam {
                        id
                        cbsTeamId
                        sportType
                        abbrev
                      }
                      tiebreakerAnswers {
                        id
                        tiebreakerQuestionId
                        value
                      }
                      picksCount
                      maxPicksCount
                      needsToMakePicks
                      maxPoints
                      correctPicks
                      createdAt
                      isMine
                      periodPoints(first: 50) @skip(if: $skipPeriodPoints) {
                        edges {
                          node {
                            id
                            fantasyPoints
                            periodId
                            poolRank
                          }
                        }
                      }
                    }
                  }
                }
                poolEditions @skip(if: $skipAncestorPools) {
                  id
                  poolId
                  seasonYear
                }
                season {
                  id
                  season
                  year
                  segments(first: 1) {
                    edges {
                      node {
                        id
                        periods(first: 50) {
                          edges {
                            node {
                              id
                              description
                              order
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        """
        return self.post(operation_name, variables, query)
