"""
NairaBet Nigeria scraper.

Platform: Altenar (sb2frontend-altenar2.biahosted.com)
Integration: nairabet

Events + odds endpoint:
  GET https://sb2frontend-altenar2.biahosted.com/api/Widget/GetEvents
  Params: culture=en-GB&timezoneOffset=300&integration=nairabet&deviceType=1
          &numFormat=en-GB&countryCode=NG&sportId={sport_id}&count=2000

Response structure (flat arrays linked by IDs):
  events[]  → id, name ("Home vs. Away"), startDate, marketIds, competitorIds
  markets[] → id, typeId, oddIds
  odds[]    → id, typeId, name, price, oddStatus, competitorId (optional)

Market typeIds:
  Football:
    1   → 1X2       (odd.typeId 1=Home, 2=Draw, 3=Away)
    18  → Total     (odd.name contains "Over 2.5" / "Under 2.5")
  Basketball:
    219 → Winner    (match odd.competitorId to event.competitorIds[0/1])
  Tennis:
    186 → Winner    (match odd.competitorId to event.competitorIds[0/1])

Sport IDs: football=66, basketball=67, tennis=68
"""
import logging
from datetime import datetime
from typing import List, Dict

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

logger = logging.getLogger(__name__)

BASE_URL = 'https://sb2frontend-altenar2.biahosted.com/api/Widget/GetEvents'
COMMON_PARAMS = (
    'culture=en-GB&timezoneOffset=300&integration=nairabet'
    '&deviceType=1&numFormat=en-GB&countryCode=NG'
)

SPORT_IDS = {
    'football':   66,
    'basketball': 67,
    'tennis':     68,
}

# {sport: {typeId: market_name}}
MARKETS = {
    'football':   {1: '1X2', 18: 'Over/Under 2.5'},
    'basketball': {219: 'Home/Away'},
    'tennis':     {186: 'Home/Away'},
}

# Altenar odd typeId → outcome label for 1x2
ODD_TYPE_MAP = {1: 'Home', 2: 'Draw', 3: 'Away'}


class NairaBetScraper(BaseScraper):

    def __init__(self):
        super().__init__('NairaBet')
        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.nairabet.com',
            'Referer': 'https://www.nairabet.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 = self._fetch(sport_id)
            events = self._parse_all(raw, sport)
        except Exception as ex:
            logger.error(f'[NairaBet] {sport} fetch error: {ex}')

        return events

    def _fetch(self, sport_id: int) -> dict:
        url = f'{BASE_URL}?{COMMON_PARAMS}&sportId={sport_id}&count=2000'
        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[int, dict] = {m['id']: m for m in raw.get('markets', [])}
        odds_by_id: Dict[int, dict]    = {o['id']: o for o in raw.get('odds', [])}
        champs_by_id: Dict[int, str]   = {c['id']: c.get('name', '') for c in raw.get('champs', [])}

        sport_markets = MARKETS.get(sport, {})
        result: List[Event] = []

        for ev in raw.get('events', []):
            ev_id    = ev.get('id', '')
            name     = (ev.get('name') or '').strip()
            comp_ids = ev.get('competitorIds', [])
            league   = champs_by_id.get(ev.get('champId', ''), '')

            # Split "Home vs. Away"
            if ' vs. ' in name:
                home, away = [t.strip() for t in name.split(' vs. ', 1)]
            elif ' vs ' in name:
                home, away = [t.strip() for t in name.split(' vs ', 1)]
            else:
                continue

            if not home or not away:
                continue

            date_str = ev.get('startDate', '')
            try:
                starts_at = datetime.fromisoformat(date_str.replace('Z', '+00:00')).replace(tzinfo=None) if date_str else None
            except Exception:
                starts_at = None

            for mkt_id in ev.get('marketIds', []):
                market = markets_by_id.get(mkt_id)
                if not market:
                    continue

                type_id = market.get('typeId')
                if type_id not in sport_markets:
                    continue

                market_name = sport_markets[type_id]
                outcomes = self._parse_outcomes(market, odds_by_id, type_id, comp_ids, sport)

                if not outcomes:
                    continue

                # Expect exactly 2 outcomes for Winner/H-A markets, 3 for 1X2
                expected = 3 if type_id == 1 else 2
                if len(outcomes) != expected:
                    continue

                result.append(Event(
                    event_id=f'nb_{ev_id}_{mkt_id}',
                    bookmaker='NairaBet',
                    sport=sport,
                    home_team=home,
                    away_team=away,
                    market=market_name,
                    outcomes=outcomes,
                    starts_at=starts_at,
                    league=league,
                ))

        return result

    def _parse_outcomes(self, market: dict, odds_by_id: Dict, type_id: int, comp_ids: list, sport: str) -> List[Outcome]:
        outcomes = []

        for oid in market.get('oddIds', []):
            odd = odds_by_id.get(oid)
            if not odd:
                continue
            if odd.get('oddStatus', 0) != 0:  # 0 = active
                continue

            price = odd.get('price', 0)
            try:
                price = float(price)
            except (TypeError, ValueError):
                continue
            if price <= 1.0:
                continue

            if type_id == 1:
                # 1X2: use odd.typeId (1=Home, 2=Draw, 3=Away)
                label = ODD_TYPE_MAP.get(odd.get('typeId'))
                if label is None:
                    continue

            elif type_id == 18:
                # Total Goals: odd.name is "Over 2.5" or "Under 2.5"
                odd_name = odd.get('name', '')
                if '2.5' not in odd_name:
                    continue
                label = 'Over' if odd_name.startswith('Over') else 'Under'

            else:
                # Winner markets (basketball 219, tennis 186):
                # use competitorId position in event.competitorIds
                cid = odd.get('competitorId')
                if cid is None or not comp_ids:
                    continue
                if cid == comp_ids[0]:
                    label = 'Home'
                elif len(comp_ids) > 1 and cid == comp_ids[1]:
                    label = 'Away'
                else:
                    continue

            outcomes.append(Outcome(name=label, odds=price, bookmaker='NairaBet'))

        return outcomes
