"""서울 버스·지하철 실시간 정보 API 클라이언트."""

from __future__ import annotations

import time
from typing import Any
from xml.etree import ElementTree

import httpx

from korea_transit_mcp_server.config import CACHE_TTL_CONGESTION, cache, config

# ============================================================
# 서울 버스 API (data.go.kr / data.seoul.go.kr)
# ============================================================

SEOUL_BUS_ARRIVAL_URL = (
    "http://ws.bus.go.kr/api/rest/stationinfo/getStationByUid"
)
SEOUL_BUS_POSITION_URL = (
    "http://ws.bus.go.kr/api/rest/buspos/getBusPosByRtid"
)
SEOUL_BUS_ROUTE_INFO_URL = (
    "http://ws.bus.go.kr/api/rest/busRouteInfo/getStaionByRoute"
)


def _parse_bus_xml(text: str) -> list[dict[str, str]]:
    """서울 버스 API XML 응답을 딕셔너리 리스트로 파싱합니다."""
    root = ElementTree.fromstring(text)
    # 응답 상태 확인 (headerCd == 0이면 성공)
    header = root.find(".//headerCd")
    if header is not None and header.text != "0":
        msg_elem = root.find(".//headerMsg")
        msg = msg_elem.text if msg_elem is not None else "Unknown error"
        raise RuntimeError(f"서울 버스 API 에러: {msg}")
    # 각 항목을 딕셔너리로 변환
    items: list[dict[str, str]] = []
    for item in root.findall(".//itemList"):
        row: dict[str, str] = {}
        for child in item:
            row[child.tag] = child.text or ""
        items.append(row)
    return items


async def get_bus_arrival(ars_id: str) -> list[dict[str, str]]:
    """버스 정류소의 실시간 도착 정보를 조회합니다.

    Args:
        ars_id: 정류소 고유번호 5자리 (e.g. "22009")
    """
    if not config.seoul_bus_api_key:
        raise RuntimeError("SEOUL_BUS_API_KEY 환경변수가 설정되지 않았습니다.")
    # API 요청 및 응답 파싱
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(SEOUL_BUS_ARRIVAL_URL, params={
            "serviceKey": config.seoul_bus_api_key,
            "arsId": ars_id,
        })
        resp.raise_for_status()
    return _parse_bus_xml(resp.text)


async def get_bus_position(route_id: str) -> list[dict[str, str]]:
    """버스 노선의 실시간 위치를 조회합니다.

    Args:
        route_id: 서울시 버스 노선 ID (e.g. "100100118")
    """
    if not config.seoul_bus_api_key:
        raise RuntimeError("SEOUL_BUS_API_KEY 환경변수가 설정되지 않았습니다.")
    # 운행 중인 모든 버스의 현재 위치 정보 조회
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(SEOUL_BUS_POSITION_URL, params={
            "serviceKey": config.seoul_bus_api_key,
            "busRouteId": route_id,
        })
        resp.raise_for_status()
    return _parse_bus_xml(resp.text)


async def get_bus_route_stations(route_id: str) -> list[dict[str, str]]:
    """버스 노선의 모든 정류장을 조회합니다.

    Args:
        route_id: 서울시 버스 노선 ID
    """
    if not config.seoul_bus_api_key:
        raise RuntimeError("SEOUL_BUS_API_KEY 환경변수가 설정되지 않았습니다.")
    # 노선 상의 전체 경유 정류장 정보 조회
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(SEOUL_BUS_ROUTE_INFO_URL, params={
            "serviceKey": config.seoul_bus_api_key,
            "busRouteId": route_id,
        })
        resp.raise_for_status()
    return _parse_bus_xml(resp.text)


# ============================================================
# 서울 지하철 API (data.seoul.go.kr)
# ============================================================

SEOUL_SUBWAY_ARRIVAL_URL = (
    "http://swopenAPI.seoul.go.kr/api/subway"
)


async def get_subway_arrival(station_name: str) -> dict[str, Any]:
    """지하철역의 실시간 도착 정보를 조회합니다.

    Args:
        station_name: 역 이름 (한글, e.g. "강남")
    """
    if not config.seoul_subway_api_key:
        raise RuntimeError("SEOUL_SUBWAY_API_KEY 환경변수가 설정되지 않았습니다.")
    # 상행/하행 열차의 실시간 도착 정보 조회 (최대 20건)
    url = (
        f"{SEOUL_SUBWAY_ARRIVAL_URL}"
        f"/{config.seoul_subway_api_key}/json/realtimeStationArrival/0/20/{station_name}"
    )
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(url)
        resp.raise_for_status()
        data = resp.json()
    # API 응답에 에러가 포함되어 있으면 예외 발생
    error_info = data.get("errorMessage")
    if error_info and error_info.get("status") != 200:
        raise RuntimeError(
            f"서울 지하철 API 에러: {error_info.get('message', 'Unknown')}"
        )
    return data


# ============================================================
# 지하철 혼잡도 (서울교통공사)
# ============================================================

CONGESTION_URL = (
    "http://swopenAPI.seoul.go.kr/api/subway"
)


async def get_subway_congestion(
    line_num: str, station_name: str, dow: str = "0"
) -> dict[str, Any]:
    """지하철 혼잡도 통계를 조회합니다.

    Args:
        line_num: 호선 번호 (e.g. "2" for 2호선)
        station_name: 역 이름
        dow: 요일 - 0=평일, 1=토요일, 2=일요일
    """
    if not config.seoul_subway_api_key:
        raise RuntimeError("SEOUL_SUBWAY_API_KEY 환경변수가 설정되지 않았습니다.")
    # TTL 캐시를 사용하여 같은 쿼리 반복 요청 방지
    cache_key = f"congestion:{line_num}:{station_name}:{dow}"
    now = time.time()
    cached = cache.get(cache_key, now)
    if cached is not None:
        return cached
    # 호선별 혼잡도 통계 조회
    url = (
        f"{CONGESTION_URL}"
        f"/{config.seoul_subway_api_key}/json/StatisticsTrnsport/1/1000/{line_num}"
    )
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(url)
        resp.raise_for_status()
        data = resp.json()
    # TTL 설정하여 캐시에 저장
    cache.set(cache_key, data, CACHE_TTL_CONGESTION, now)
    return data
