"""대중교통 경로 검색 및 노선 정보 도구."""

from __future__ import annotations

from typing import Any

from korea_transit_mcp_server.clients import odsay

# ODsay 교통 수단 타입 매핑
TRAFFIC_TYPE = {1: "지하철", 2: "버스", 3: "도보"}
BUS_TYPE = {
    1: "일반", 2: "좌석", 3: "마을", 4: "직행좌석", 5: "공항",
    6: "간선", 7: "외곽", 10: "마을", 11: "간선", 12: "지선",
    13: "순환", 14: "광역", 15: "급행", 16: "관광", 26: "급행간선",
}


def _format_duration(minutes: int) -> str:
    if minutes < 60:
        return f"{minutes}분"
    h, m = divmod(minutes, 60)
    return f"{h}시간 {m}분" if m else f"{h}시간"


def _format_fare(fare: int) -> str:
    return f"{fare:,}원"


def _format_sub_path(sub: dict[str, Any]) -> str:
    """경로의 한 구간을 포맷합니다."""
    traffic = sub.get("trafficType", 0)
    ttype = TRAFFIC_TYPE.get(traffic, "기타")

    if traffic == 3:  # 도보
        dist = sub.get("distance", 0)
        sec = sub.get("sectionTime", 0)
        return f"🚶 도보 {dist}m ({sec}분)"
    elif traffic == 1:  # 지하철
        lanes = sub.get("lane", [])
        lane_name = lanes[0].get("name", "") if lanes else ""
        start = sub.get("startName", "")
        end = sub.get("endName", "")
        count = sub.get("stationCount", 0)
        sec = sub.get("sectionTime", 0)
        return f"🚇 {lane_name}: {start} → {end} ({count}개역, {sec}분)"
    elif traffic == 2:  # 버스
        lanes = sub.get("lane", [])
        bus_names = [ln.get("busNo", "") for ln in lanes[:3]]
        bus_str = "/".join(bus_names)
        start = sub.get("startName", "")
        end = sub.get("endName", "")
        count = sub.get("stationCount", 0)
        sec = sub.get("sectionTime", 0)
        return f"🚌 버스 {bus_str}: {start} → {end} ({count}정거장, {sec}분)"
    return f"기타 구간: {sec}분"


def format_route_result(data: dict[str, Any]) -> str:
    """ODsay 경로 검색 결과를 읽기 쉬운 텍스트로 포맷합니다."""
    result = data.get("result", {})
    if not result:
        return "경로를 찾을 수 없습니다."

    paths = result.get("path", [])
    if not paths:
        return "경로를 찾을 수 없습니다."

    lines: list[str] = []
    lines.append(f"총 {len(paths)}개 경로를 찾았습니다.\n")

    for i, path in enumerate(paths, 1):
        info = path.get("info", {})
        total_time = info.get("totalTime", 0)
        total_walk = info.get("totalWalk", 0)
        payment = info.get("payment", 0)
        transfer = info.get("busTransitCount", 0) + info.get("subwayTransitCount", 0)

        lines.append(f"--- 경로 {i} ---")
        lines.append(
            f"소요시간: {_format_duration(total_time)} | "
            f"환승: {transfer}회 | "
            f"요금: {_format_fare(payment)} | "
            f"도보: {total_walk}m"
        )

        sub_paths = path.get("subPath", [])
        for sub in sub_paths:
            segment = _format_sub_path(sub)
            if segment:
                lines.append(f"  {segment}")
        lines.append("")

    return "\n".join(lines)


async def search_transit_route(
    start: str,
    end: str,
    search_type: int = 0,
) -> str:
    """대중교통 경로를 검색합니다.

    Args:
        start: 출발지 (좌표 "경도,위도" 또는 검색어)
        end: 도착지 (좌표 "경도,위도" 또는 검색어)
        search_type: 0=추천, 1=최소시간, 2=최소환승
    """
    sx, sy = await _resolve_location(start)
    ex, ey = await _resolve_location(end)
    data = await odsay.search_pub_trans_path(sx, sy, ex, ey, search_type)
    return format_route_result(data)


async def _resolve_location(location: str) -> tuple[float, float]:
    """Resolve a location string to (longitude, latitude) coordinates."""
    # Check if it's already coordinates "lng,lat"
    parts = location.split(",")
    if len(parts) == 2:
        try:
            lng, lat = float(parts[0].strip()), float(parts[1].strip())
            if 124 <= lng <= 132 and 33 <= lat <= 39:
                return lng, lat
            if 33 <= lng <= 39 and 124 <= lat <= 132:
                return lat, lng
        except ValueError:
            pass

    # Search by keyword
    data = await odsay.search_station(location)
    result = data.get("result", {})
    stations = result.get("station", [])
    if not stations:
        raise ValueError(f"'{location}'에 해당하는 정류장/역을 찾을 수 없습니다.")
    station = stations[0]
    return float(station["x"]), float(station["y"])


async def get_line_info(line_name: str) -> str:
    """노선 정보를 조회합니다 (경유 정류장, 운행 정보).

    Args:
        line_name: 노선명 (e.g. "2호선", "버스 333")
    """
    # Try subway first
    if "호선" in line_name or "line" in line_name.lower():
        station_data = await odsay.subway_station_info(line_name.replace("호선", "").strip())
        result = station_data.get("result", {})
        if result:
            return _format_subway_line_info(result, line_name)

    # Try bus
    data = await odsay.search_station(line_name, station_class=1)
    result = data.get("result", {})
    stations = result.get("station", [])
    if stations:
        lines: list[str] = [f"'{line_name}' 관련 정류장:"]
        for s in stations[:10]:
            lines.append(f"  - {s.get('stationName', '')} (ID: {s.get('stationID', '')})")
        return "\n".join(lines)

    return f"'{line_name}' 노선 정보를 찾을 수 없습니다."


def _format_subway_line_info(result: dict[str, Any], name: str) -> str:
    """Format subway line info."""
    lines: list[str] = [f"🚇 {name} 정보"]
    stations_data = result.get("stationList", result.get("station", []))
    if isinstance(stations_data, list):
        station_names = [s.get("stationName", "") for s in stations_data[:30]]
        if station_names:
            lines.append(f"경유역 ({len(station_names)}개): {' → '.join(station_names)}")
            if len(stations_data) > 30:
                lines.append(f"  ... 외 {len(stations_data) - 30}개역")
    return "\n".join(lines) if len(lines) > 1 else f"'{name}' 상세 정보를 가져올 수 없습니다."
