"""
Live quote KPIs from Simpro REST API, scoped by date range (Australia/Perth calendar dates).
Results cached in-memory (see simpro_api_limits.SIMPRO_API_CACHE_TTL_SECONDS) per branch + range.
"""
import logging
import time
from datetime import date, datetime
from typing import Dict, Optional, Tuple
from zoneinfo import ZoneInfo

import asyncio
from asgiref.sync import sync_to_async

from app.config import settings
from app.services.simpro_api_limits import SIMPRO_API_CACHE_TTL_SECONDS

logger = logging.getLogger(__name__)

_quote_cache: Dict[str, Tuple[float, dict]] = {}

BRANCH_ID_TO_NAME = {"branch1": "Busselton", "branch2": "Bunbury", "branch3": "Mandurah"}


def _cache_key(branch_id: str, d0: date, d1: date) -> str:
    return f"{branch_id}:{d0.isoformat()}:{d1.isoformat()}"


def default_quote_range_perth() -> Tuple[date, date]:
    """First day of current month through today (Perth) — used when API caller omits range."""
    z = ZoneInfo("Australia/Perth")
    today = datetime.now(z).date()
    return today.replace(day=1), today


async def get_quote_data_for_branch(
    branch_id: str,
    date_from: Optional[date] = None,
    date_to: Optional[date] = None,
    force_refresh: bool = False,
) -> dict:
    """
    Quote aggregates for one Simpro branch (all companies), same shape as legacy CSV parser.
    """
    if date_from is None or date_to is None:
        date_from, date_to = default_quote_range_perth()
    if date_from > date_to:
        date_from, date_to = date_to, date_from

    key = _cache_key(branch_id, date_from, date_to)
    now = time.time()
    if not force_refresh and key in _quote_cache:
        ts, data = _quote_cache[key]
        if now - ts < SIMPRO_API_CACHE_TTL_SECONDS:
            return data

    if branch_id not in settings.BRANCHES:
        return {
            "quotesCreated": 0,
            "totalValueQuoted": 0.0,
            "avgQuoteValue": 0.0,
            "quotesConverted": 0,
            "valueConverted": 0.0,
            "conversionRate": 0.0,
            "departments": [],
        }

    from app.services.simpro_client import SimProClient

    try:
        client = await sync_to_async(SimProClient)(branch_id)
        payload = await client.fetch_quote_aggregates_for_branch(date_from, date_to)
    except Exception as e:
        logger.warning("Simpro quote fetch failed for %s: %s", branch_id, e)
        client = await sync_to_async(SimProClient)(branch_id)
        payload = client._empty_quote_aggregates()

    _quote_cache[key] = (now, payload)
    return payload


async def get_quote_data_all_branches(date_from: date, date_to: date) -> Dict[str, dict]:
    """Quote aggregates for Bunbury, Busselton, Mandurah (directors panel key order)."""

    order = [
        ("branch2", "Bunbury"),
        ("branch1", "Busselton"),
        ("branch3", "Mandurah"),
    ]
    tasks = []
    names = []
    for bid, bname in order:
        if bid not in settings.BRANCHES:
            continue
        names.append(bname)
        tasks.append(get_quote_data_for_branch(bid, date_from, date_to))

    if not tasks:
        return {}

    results = await asyncio.gather(*tasks, return_exceptions=True)
    out: Dict[str, dict] = {}
    for bname, res in zip(names, results):
        if isinstance(res, Exception):
            logger.warning("Quote branch fetch failed %s: %s", bname, res)
            out[bname] = {
                "quotesCreated": 0,
                "totalValueQuoted": 0.0,
                "avgQuoteValue": 0.0,
                "quotesConverted": 0,
                "valueConverted": 0.0,
                "conversionRate": 0.0,
                "departments": [],
            }
        else:
            out[bname] = res
    return out
