# -*- coding: utf-8 -*-
"""
LiveScoreJSON - official thin Python SDK
Soccer live scores, stats, lineups, tables, head2head, transfers and more.
All responses use an Opta-compatible JSON envelope.

Zero third-party dependencies (uses urllib from the stdlib). Python 3.7+.
Docs: https://livescorejson.com/docs/en.html

Quick start:
    from livescorejson import LiveScoreJSON
    api = LiveScoreJSON(api_key="ljson_live_...")
    live = api.get_matches_live(lang="en")
    print(live["data"])
"""
import json
import urllib.parse
import urllib.request


class LiveScoreJSONError(Exception):
    """Raised on a non-2xx API response. .status and .body hold the details."""
    def __init__(self, status, body):
        self.status = status
        self.body = body
        msg = body.get("error") if isinstance(body, dict) else str(body)
        super().__init__("LiveScoreJSON %s: %s" % (status, msg))


class LiveScoreJSON:
    def __init__(self, api_key, base_url="https://livescorejson.com/api",
                 lang=None, auth_mode="bearer", timeout=30):
        """
        api_key   : your key (ljson_live_...). Required for the direct/portal channel.
        base_url  : default https://livescorejson.com/api
        lang      : default language applied to every call (en/tr/es/de/fr).
        auth_mode : 'bearer' => Authorization: Bearer; 'header' => X-API-Key.
        """
        if not api_key:
            raise ValueError("LiveScoreJSON: api_key is required")
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")
        self.lang = lang
        self.auth_mode = auth_mode
        self.timeout = timeout

    def call(self, endpoint, **params):
        """Low-level call. Returns the parsed JSON envelope; raises LiveScoreJSONError on non-2xx."""
        if self.lang and "lang" not in params:
            params["lang"] = self.lang
        params = {k: v for k, v in params.items() if v is not None}
        url = "%s/%s.php" % (self.base_url, endpoint)
        if params:
            url += "?" + urllib.parse.urlencode(params)
        headers = {"Accept": "application/json"}
        if self.auth_mode == "header":
            headers["X-API-Key"] = self.api_key
        else:
            headers["Authorization"] = "Bearer " + self.api_key
        req = urllib.request.Request(url, headers=headers)
        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as resp:
                return json.loads(resp.read().decode("utf-8"))
        except urllib.error.HTTPError as e:
            raw = e.read().decode("utf-8", "replace")
            try:
                body = json.loads(raw)
            except ValueError:
                body = {"error": raw}
            raise LiveScoreJSONError(e.code, body)

    def ws_token(self):
        """Fetch a short-lived WebSocket token (see get_ws_token)."""
        return self.call("get_ws_token")

    # ---- Endpoint methods (one per published endpoint) ----
    def get_areas(self, **params):
        """get_areas — https://livescorejson.com/docs/en.html#get_areas"""
        return self.call('get_areas', **params)

    def get_competitions(self, **params):
        """get_competitions — https://livescorejson.com/docs/en.html#get_competitions"""
        return self.call('get_competitions', **params)

    def get_seasons(self, **params):
        """get_seasons — https://livescorejson.com/docs/en.html#get_seasons"""
        return self.call('get_seasons', **params)

    def get_rounds(self, **params):
        """get_rounds — https://livescorejson.com/docs/en.html#get_rounds"""
        return self.call('get_rounds', **params)

    def get_groups(self, **params):
        """get_groups — https://livescorejson.com/docs/en.html#get_groups"""
        return self.call('get_groups', **params)

    def get_teams(self, **params):
        """get_teams — https://livescorejson.com/docs/en.html#get_teams"""
        return self.call('get_teams', **params)

    def get_squads(self, **params):
        """get_squads — https://livescorejson.com/docs/en.html#get_squads"""
        return self.call('get_squads', **params)

    def get_squads_changes(self, **params):
        """get_squads_changes — https://livescorejson.com/docs/en.html#get_squads_changes"""
        return self.call('get_squads_changes', **params)

    def get_venues(self, **params):
        """get_venues — https://livescorejson.com/docs/en.html#get_venues"""
        return self.call('get_venues', **params)

    def get_referees(self, **params):
        """get_referees — https://livescorejson.com/docs/en.html#get_referees"""
        return self.call('get_referees', **params)

    def get_matches(self, **params):
        """get_matches — https://livescorejson.com/docs/en.html#get_matches"""
        return self.call('get_matches', **params)

    def get_matches_live(self, **params):
        """get_matches_live — https://livescorejson.com/docs/en.html#get_matches_live"""
        return self.call('get_matches_live', **params)

    def get_matches_live_updates(self, **params):
        """get_matches_live_updates — https://livescorejson.com/docs/en.html#get_matches_live_updates"""
        return self.call('get_matches_live_updates', **params)

    def get_match_statistics(self, **params):
        """get_match_statistics — https://livescorejson.com/docs/en.html#get_match_statistics"""
        return self.call('get_match_statistics', **params)

    def get_match_formations(self, **params):
        """get_match_formations — https://livescorejson.com/docs/en.html#get_match_formations"""
        return self.call('get_match_formations', **params)

    def get_match_commentary(self, **params):
        """get_match_commentary — https://livescorejson.com/docs/en.html#get_match_commentary"""
        return self.call('get_match_commentary', **params)

    def get_match_extra(self, **params):
        """get_match_extra — https://livescorejson.com/docs/en.html#get_match_extra"""
        return self.call('get_match_extra', **params)

    def get_match_editorials(self, **params):
        """get_match_editorials — https://livescorejson.com/docs/en.html#get_match_editorials"""
        return self.call('get_match_editorials', **params)

    def get_tables(self, **params):
        """get_tables — https://livescorejson.com/docs/en.html#get_tables"""
        return self.call('get_tables', **params)

    def get_tables_live(self, **params):
        """get_tables_live — https://livescorejson.com/docs/en.html#get_tables_live"""
        return self.call('get_tables_live', **params)

    def get_tables_cumulative(self, **params):
        """get_tables_cumulative — https://livescorejson.com/docs/en.html#get_tables_cumulative"""
        return self.call('get_tables_cumulative', **params)

    def get_head2head(self, **params):
        """get_head2head — https://livescorejson.com/docs/en.html#get_head2head"""
        return self.call('get_head2head', **params)

    def get_transfers(self, **params):
        """get_transfers — https://livescorejson.com/docs/en.html#get_transfers"""
        return self.call('get_transfers', **params)

    def get_players_abroad(self, **params):
        """get_players_abroad — https://livescorejson.com/docs/en.html#get_players_abroad"""
        return self.call('get_players_abroad', **params)

    def get_career(self, **params):
        """get_career — https://livescorejson.com/docs/en.html#get_career"""
        return self.call('get_career', **params)

    def get_player_statistics(self, **params):
        """get_player_statistics — https://livescorejson.com/docs/en.html#get_player_statistics"""
        return self.call('get_player_statistics', **params)

    def get_team_statistics(self, **params):
        """get_team_statistics — https://livescorejson.com/docs/en.html#get_team_statistics"""
        return self.call('get_team_statistics', **params)

    def get_injuries(self, **params):
        """get_injuries — https://livescorejson.com/docs/en.html#get_injuries"""
        return self.call('get_injuries', **params)

    def get_suspensions(self, **params):
        """get_suspensions — https://livescorejson.com/docs/en.html#get_suspensions"""
        return self.call('get_suspensions', **params)

    def get_trophies(self, **params):
        """get_trophies — https://livescorejson.com/docs/en.html#get_trophies"""
        return self.call('get_trophies', **params)

    def get_rankings(self, **params):
        """get_rankings — https://livescorejson.com/docs/en.html#get_rankings"""
        return self.call('get_rankings', **params)

    def get_deleted(self, **params):
        """get_deleted — https://livescorejson.com/docs/en.html#get_deleted"""
        return self.call('get_deleted', **params)

    def get_betting_statistics(self, **params):
        """get_betting_statistics — https://livescorejson.com/docs/en.html#get_betting_statistics"""
        return self.call('get_betting_statistics', **params)

    def get_runningball_matches(self, **params):
        """get_runningball_matches — https://livescorejson.com/docs/en.html#get_runningball_matches"""
        return self.call('get_runningball_matches', **params)

    def get_hashtags(self, **params):
        """get_hashtags — https://livescorejson.com/docs/en.html#get_hashtags"""
        return self.call('get_hashtags', **params)

    def get_ws_token(self, **params):
        """get_ws_token — https://livescorejson.com/docs/en.html#get_ws_token"""
        return self.call('get_ws_token', **params)
