#!/usr/bin/env python3
"""
Shared TMX Money GraphQL quote fetcher.

Single source of truth for talking to the TMX API — fetch_prices.py and
generate_retrospective.py both import get_quote() from here instead of each
keeping their own copy, so the query/parsing logic can't drift between them.
"""
import json
import urllib.request

TMX_URL = 'https://app-money.tmx.com/graphql'


def get_quote(ticker, timeout=10):
    """Fetch {'price': float, 'changePct': float|None} for a TSX ticker like 'SU.TO'.
    Returns None if the ticker can't be resolved or the request fails."""
    ticker = ticker.upper()
    _EXCHANGE_SUFFIXES = ('.TO', '.V', '.CN', '.NE')
    for suffix in _EXCHANGE_SUFFIXES:
        if ticker.endswith(suffix):
            ticker = ticker[:-len(suffix)]
            break
    sym = ticker
    body = json.dumps({
        'operationName': 'getQuoteBySymbol',
        'variables':     {'symbol': sym, 'locale': 'en'},
        'query':         'query getQuoteBySymbol($symbol:String,$locale:String){getQuoteBySymbol(symbol:$symbol,locale:$locale){symbol price percentChange}}',
    }).encode()
    req = urllib.request.Request(
        TMX_URL,
        data=body,
        headers={'Content-Type': 'application/json', 'Accept': 'application/json'},
        method='POST',
    )
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            raw = json.loads(resp.read())
        q     = raw.get('data', {}).get('getQuoteBySymbol', {})
        price = q.get('price')
        chg   = q.get('percentChange')
        if price is None:
            return None
        return {'price': float(price), 'changePct': float(chg) if chg is not None else None}
    except Exception:
        return None
