"""
Betway Nigeria scraper.

Endpoints discovered via Playwright network interception on betway.com.ng

Events + odds:
  GET https://feeds-roa2.betwayafrica.com/br/_apis/sport/v1/BetBook/Highlights/
  Params: countryCode=NG, sportId=soccer, marketTypes=[Win/Draw/Win],[Total Goals]
          cultureCode=en-US, boostedOnly=false, Skip=0, Take=200

Response structure (flat arrays linked by ID):
  events[]   → eventId, homeTeam, awayTeam, expectedStartEpoch, isLive
  markets[]  → marketId, name ("[Win/Draw/Win]" / "[Total Goals]"), eventId,
               handicap, isSquashedParent, squashedMarketIds
  outcomes[] → outcomeId, name, marketId, eventId, handicap, isTradingActive,
               originalMarketId
  prices[]   → outcomeId, priceDecimal

Market filtering:
  - 1X2:  market.name == "[Win/Draw/Win]"
  - O/U:  market.name == "[Total Goals]" (squashed parent; sub-markets in
          squashedMarketIds, filter by originalMarketId containing "total=2.5")

Outcome labels:
  - 1X2:  outcome.name matches event.homeTeam → "Home"
          outcome.name == "Draw"             → "Draw"
          outcome.name matches event.awayTeam → "Away"
  - O/U:  outcome.name.strip() "Over"/"Under" where handicap == 2.5

Note: The Highlights endpoint is a curated view (~39 events).
No auth required; Origin + Referer headers sufficient.
"""
import logging
from datetime import datetime
from typing import List, Dict, Optional

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

logger = logging.getLogger(__name__)

BASE_URL = 'https://feeds-roa2.betwayafrica.com/br/_apis/sport/v1/BetBook/Highlights/'

SPORT_CONFIG = {
    'football': {
        'sportId': 'soccer',
        'marketTypes': ['[Win/Draw/Win]', '[Total Goals]'],
    },
}


class BetwayScraper(BaseScraper):

    def __init__(self):
        super().__init__('Betway')
        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, */*',
            'Origin':  'https://www.betway.com.ng',
            'Referer': 'https://www.betway.com.ng/',
        }

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

        events: List[Event] = []
        try:
            raw = self._fetch(cfg['sportId'], cfg['marketTypes'])
            events = self._parse_all(raw, sport)
        except Exception as ex:
            logger.error(f'[Betway] {sport} fetch error: {ex}')

        return events

    def _fetch(self, sport_id: str, market_types: List[str]) -> dict:
        params = {
            'countryCode':  'NG',
            'sportId':      sport_id,
            'Skip':         '0',
            'Take':         '200',
            'cultureCode':  'en-US',
            'isEsport':     'false',
            'boostedOnly':  'false',
        }
        # Build URL manually — marketTypes is a repeated param
        base_qs = '&'.join(f'{k}={v}' for k, v in params.items())
        mkt_qs  = '&'.join(f'marketTypes={mt.replace("/", "%2F")}' for mt in market_types)
        url = f'{BASE_URL}?{base_qs}&{mkt_qs}'
        r = self.session.get(url, timeout=20)
        r.raise_for_status()
        return r.json()

    def _parse_all(self, raw: dict, sport: str) -> List[Event]:
        # Build lookup dicts
        markets_by_id:  Dict[str, dict] = {m['marketId']:   m for m in raw.get('markets',  [])}
        outcomes_by_id: Dict[str, dict] = {o['outcomeId']:  o for o in raw.get('outcomes', [])}
        prices_by_id:   Dict[str, float] = {
            p['outcomeId']: p['priceDecimal']
            for p in raw.get('prices', [])
            if p.get('priceDecimal')
        }

        # Group outcomes + prices by eventId
        outcomes_by_event: Dict[int, List[dict]] = {}
        for o in raw.get('outcomes', []):
            ev_id = o.get('eventId')
            if ev_id is not None:
                outcomes_by_event.setdefault(ev_id, []).append(o)

        # Group markets by eventId
        markets_by_event: Dict[int, List[dict]] = {}
        for m in raw.get('markets', []):
            ev_id = m.get('eventId')
            if ev_id is not None:
                markets_by_event.setdefault(ev_id, []).append(m)

        result: List[Event] = []

        for ev in raw.get('events', []):
            if ev.get('isLive') or not ev.get('isActive'):
                continue

            ev_id    = ev['eventId']
            home     = ev.get('homeTeam', '').strip()
            away     = ev.get('awayTeam', '').strip()
            league   = ev.get('league', '').strip()
            if not home or not away:
                continue

            ts = ev.get('expectedStartEpoch')
            try:
                starts_at = datetime.utcfromtimestamp(ts) if ts else None
            except Exception:
                starts_at = None

            ev_markets  = markets_by_event.get(ev_id, [])
            ev_outcomes = outcomes_by_event.get(ev_id, [])

            for market in ev_markets:
                mkt_name = market.get('name', '')

                if mkt_name == '[Win/Draw/Win]' and not market.get('isSquashedParent'):
                    parsed = self._parse_1x2(market, ev_outcomes, prices_by_id, home, away)
                    if parsed:
                        result.append(Event(
                            event_id  = f'bw_{ev_id}_{market["marketId"]}',
                            bookmaker = 'Betway',
                            sport     = sport,
                            home_team = home,
                            away_team = away,
                            market    = '1X2',
                            outcomes  = parsed,
                            starts_at = starts_at,
                            league    = league,
                        ))

                elif mkt_name == '[Total Goals]' and market.get('isSquashedParent'):
                    parsed = self._parse_total_goals(market, ev_outcomes, prices_by_id)
                    if parsed:
                        result.append(Event(
                            event_id  = f'bw_{ev_id}_ou25',
                            bookmaker = 'Betway',
                            sport     = sport,
                            home_team = home,
                            away_team = away,
                            market    = 'Over/Under 2.5',
                            outcomes  = parsed,
                            starts_at = starts_at,
                            league    = league,
                        ))

        return result

    def _parse_1x2(self, market: dict, all_outcomes: List[dict], prices: Dict, home: str, away: str) -> Optional[List[Outcome]]:
        mid = market['marketId']
        oc_list = [o for o in all_outcomes if o.get('marketId') == mid and o.get('isTradingActive')]

        result = []
        for o in oc_list:
            price = prices.get(o['outcomeId'])
            if not price or price <= 1.0:
                continue

            name = o.get('name', '').strip()
            if name == home:
                label = 'Home'
            elif name == away:
                label = 'Away'
            elif name.lower() == 'draw':
                label = 'Draw'
            else:
                continue

            result.append(Outcome(name=label, odds=price, bookmaker='Betway'))

        if len(result) == 3:
            return result
        return None

    def _parse_total_goals(self, market: dict, all_outcomes: List[dict], prices: Dict) -> Optional[List[Outcome]]:
        # The squashed parent contains outcomes for all lines; filter to 2.5 via originalMarketId
        # Deduplicate by outcomeId (same outcome appears under parent + sub-market)
        seen = set()
        oc_25 = []
        for o in all_outcomes:
            if (o.get('originalMarketId', '').endswith('total=2.5~')
                    and o.get('isTradingActive')
                    and o['outcomeId'] not in seen):
                seen.add(o['outcomeId'])
                oc_25.append(o)

        result = []
        for o in oc_25:
            price = prices.get(o['outcomeId'])
            if not price or price <= 1.0:
                continue

            name = o.get('name', '').strip()
            if name == 'Over':
                label = 'Over'
            elif name == 'Under':
                label = 'Under'
            else:
                continue

            result.append(Outcome(name=label, odds=price, bookmaker='Betway'))

        if len(result) == 2:
            return result
        return None
