"""
BetKing Nigeria scraper.

Endpoints discovered via Playwright network interception on betking.com/sports/s/football/

Events + odds:
  GET https://sportsapicdn-desktop.betking.com/api/feeds/prematch/mostpopularsports/en/{sport_id}/{days}/{count}/

Response structure:
  data[0]['AreaMatches'][0]['Items']  → list of events
  Item fields:
    ItemName  → "Home Team - Away Team"
    ItemDate  → ISO 8601 start time
    ItemID    → event ID
    OddsCollection → list of markets, each with MatchOdds (deduplicated by MatchOddsID)

Market IDs (OddsTypeID):
  Football:
    110  → 1X2        OddName: "1"=Home, "X"=Draw, "2"=Away
    160  → Total Goals OddName: "Over"/"Under", SpecialValue = line (filter for 2.5)
  Basketball:
    9300 → Moneyline  OddName: "1"=Home, "2"=Away
  Tennis:
    9388 → 1-2        OddName: "1"=Home, "2"=Away

Note: MatchOdds entries are duplicated — deduplicate by MatchOddsID before parsing.
"""
import logging
from datetime import datetime, timezone
from typing import List

from scrapers.base import BaseScraper
from core.models import Event, Outcome

logger = logging.getLogger(__name__)

BASE_URL = "https://sportsapicdn-desktop.betking.com/api/feeds/prematch/mostpopularsports/en"

# BetKing sport IDs
SPORT_IDS = {
    'football':   1,
    'basketball': 2,
    'tennis':     5,
}

# {sport: {OddsTypeID: (market_name, {OddName: label}, special_value_filter)}}
# special_value_filter=None means accept all; a float means only accept that SpecialValue
MARKETS = {
    'football': {
        110: ('1X2',            {'1': 'Home', 'X': 'Draw', '2': 'Away'}, None),
        160: ('Over/Under 2.5', {'Over': 'Over', 'Under': 'Under'},       2.5),
    },
    'basketball': {
        9300: ('Home/Away', {'1': 'Home', '2': 'Away'}, None),
    },
    'tennis': {
        9388: ('Home/Away', {'1': 'Home', '2': 'Away'}, None),
    },
}

DAYS_AHEAD = 7
EVENT_COUNT = 200   # max events per request


class BetKingScraper(BaseScraper):

    def __init__(self):
        super().__init__('BetKing')
        self.session.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Accept': 'application/json, text/plain, */*',
            'Referer': 'https://www.betking.com/sports/s/football/',
            'Origin': 'https://www.betking.com',
        }

    def get_events(self, sport: str) -> List[Event]:
        sport_id = SPORT_IDS.get(sport)
        if not sport_id:
            return []

        events: List[Event] = []
        try:
            raw_items = self._fetch(sport_id)
            for item in raw_items:
                events.extend(self._parse(item, sport))
        except Exception as ex:
            logger.error(f"[BetKing] {sport} fetch error: {ex}")

        return events

    def _fetch(self, sport_id: int) -> list:
        url = f"{BASE_URL}/{sport_id}/{DAYS_AHEAD}/{EVENT_COUNT}/"
        r = self.session.get(url, timeout=20)
        r.raise_for_status()
        data = r.json()
        # data[0]['AreaMatches'][0]['Items']
        try:
            return data[0]['AreaMatches'][0]['Items']
        except (IndexError, KeyError, TypeError):
            return []

    def _parse(self, item: dict, sport: str) -> List[Event]:
        name = (item.get('ItemName') or '').strip()
        if ' - ' not in name:
            return []

        home, away = [t.strip() for t in name.split(' - ', 1)]
        if not home or not away:
            return []

        league = (item.get('TournamentName') or '').strip()
        date_str = item.get('ItemDate', '')
        try:
            # Format: "2026-04-11T13:30:00+02:00" — strip tz so it's consistent with other scrapers
            starts_at = datetime.fromisoformat(date_str).astimezone(timezone.utc).replace(tzinfo=None) if date_str else None
        except Exception:
            starts_at = None

        event_id_base = str(item.get('ItemID', ''))
        sport_markets = MARKETS.get(sport, {})
        result: List[Event] = []

        for oc in item.get('OddsCollection', []):
            odds_type = oc.get('OddsType', {})
            type_id = odds_type.get('OddsTypeID')
            if type_id not in sport_markets:
                continue

            market_name, name_map, sv_filter = sport_markets[type_id]

            # Deduplicate MatchOdds by MatchOddsID
            seen_ids = set()
            unique_odds = []
            for mo in oc.get('MatchOdds', []):
                mid = mo.get('MatchOddsID')
                if mid not in seen_ids:
                    seen_ids.add(mid)
                    unique_odds.append(mo)

            outcomes = []
            for mo in unique_odds:
                attr = mo.get('OddAttribute', {})
                odd_name = attr.get('OddName', '')
                sv = attr.get('SpecialValue')

                # Apply special value filter (e.g. only Over/Under 2.5)
                if sv_filter is not None and sv != sv_filter:
                    continue

                label = name_map.get(odd_name)
                if label is None:
                    continue

                try:
                    odds_val = float(mo['Outcome']['OddOutcome'])
                except (KeyError, TypeError, ValueError):
                    continue

                if odds_val > 1.0:
                    outcomes.append(Outcome(name=label, odds=odds_val, bookmaker='BetKing'))

            if len(outcomes) == len(name_map):
                result.append(Event(
                    event_id=f"bk_{event_id_base}_{type_id}",
                    bookmaker='BetKing',
                    sport=sport,
                    home_team=home,
                    away_team=away,
                    market=market_name,
                    outcomes=outcomes,
                    starts_at=starts_at,
                    league=league,
                ))

        return result
