"""yfinance용 AWS API Gateway IP rotation 헬퍼.

Yahoo Finance가 IP 기반 레이트리밋을 걸기 시작하면 이 모듈로 전환하세요.
AWS API Gateway 리전의 IP 풀을 이용해 사실상 무제한 IP 로테이션.

**필수 준비사항**:
    pip install requests-ip-rotator
    AWS 계정 + credentials (~/.aws/credentials 또는 AWS_ACCESS_KEY_ID/SECRET 환경변수)

**비용**:
    - AWS 무료 티어: 첫 12개월, 월 1M 요청 무료
    - 이후: $3.50 / 1M 요청 (리전당)
    - 데이터 전송료 추가 (작은 응답이라 거의 무시 가능)

**리스크**:
    - Yahoo가 AWS ASN 대역 전체를 차단하면 무용지물
    - 대규모 스크래퍼들은 residential proxy 선호

사용법:
    from backend.app.services.yfinance_proxy import ip_rotating_session
    import yfinance as yf

    with ip_rotating_session() as session:
        data = yf.Ticker("AAPL", session=session).history(period="60d")
        news = yf.Ticker("AAPL", session=session).news
        tickers = yf.Tickers("AAPL MSFT NVDA", session=session)
        prices = tickers.history(period="60d", group_by="ticker")
    # 컨텍스트 종료 시 gateway 자동 shutdown
"""
from __future__ import annotations

import logging
from contextlib import contextmanager
from typing import Iterator

import requests

logger = logging.getLogger(__name__)


# yfinance 가 사용하는 주요 Yahoo Finance 엔드포인트
_YAHOO_ENDPOINTS = (
    "https://query1.finance.yahoo.com",
    "https://query2.finance.yahoo.com",
    "https://fc.yahoo.com",
)

# 기본 AWS 리전 (IP 풀 다양성 확보를 위해 미국 3개 + 일본 1개)
DEFAULT_REGIONS = (
    "us-east-1",
    "us-west-2",
    "us-east-2",
    "ap-northeast-1",  # 도쿄 - 일본 주식 데이터 근접성
)


class IpRotationNotAvailable(RuntimeError):
    """requests-ip-rotator 미설치 또는 AWS 설정 누락."""


def _import_rotator():
    try:
        from requests_ip_rotator import ApiGateway  # type: ignore
        return ApiGateway
    except ImportError as exc:
        raise IpRotationNotAvailable(
            "requests-ip-rotator not installed. Run: pip install requests-ip-rotator"
        ) from exc


def create_rotating_session(
    endpoints: tuple[str, ...] = _YAHOO_ENDPOINTS,
    regions: tuple[str, ...] = DEFAULT_REGIONS,
    access_key_id: str | None = None,
    access_key_secret: str | None = None,
    persistent: bool = True,
) -> tuple[requests.Session, list]:
    """IP rotation 세션 생성.

    Args:
        endpoints: mount 할 타겟 도메인들 (Yahoo Finance 기본값)
        regions: AWS 리전 목록 (IP 풀 다양성)
        access_key_id / access_key_secret: 명시적으로 지정하지 않으면 AWS SDK
            기본 chain (~/.aws/credentials, env vars) 사용
        persistent: True면 gateway를 AWS에 영구 등록 (shutdown 해도 유지) →
            다음 실행 시 재사용 가능. AWS CreateRestApi rate limit 우회.

    Returns:
        (session, gateways) - session 은 mount 완료된 requests.Session,
        gateways 는 shutdown_gateways() 에 넘길 ApiGateway 객체 리스트.
    """
    ApiGateway = _import_rotator()
    session = requests.Session()
    gateways = []
    for endpoint in endpoints:
        kwargs: dict = {"regions": list(regions)}
        if access_key_id and access_key_secret:
            kwargs["access_key_id"] = access_key_id
            kwargs["access_key_secret"] = access_key_secret
        gateway = ApiGateway(endpoint, **kwargs)
        try:
            # require_manual_deletion=True: shutdown 해도 AWS에 남아있음 → 재사용 가능
            gateway.start(force=False, require_manual_deletion=persistent)
        except Exception as exc:  # noqa: BLE001
            logger.error("Failed to start gateway for %s: %s", endpoint, exc)
            # 이미 시작된 gateway 정리 (persistent 상관없이 session 단위 shutdown)
            shutdown_gateways(gateways, persistent=persistent)
            raise IpRotationNotAvailable(f"Gateway start failed: {exc}") from exc
        session.mount(endpoint, gateway)
        gateways.append(gateway)
        logger.info("IP rotation gateway started: %s (regions=%s, persistent=%s)", endpoint, regions, persistent)
    return session, gateways


def shutdown_gateways(gateways: list, persistent: bool = True) -> None:
    """Gateway 종료. persistent=True면 AWS 리소스 유지 (다음 실행 때 재사용)."""
    if persistent:
        # AWS에서 삭제하지 않음 — 다음 create_rotating_session에서 재사용됨
        logger.info("Gateways kept alive (persistent=True) for reuse")
        return
    for gateway in gateways:
        try:
            gateway.shutdown()
        except Exception as exc:  # noqa: BLE001
            logger.warning("Gateway shutdown failed: %s", exc)


@contextmanager
def ip_rotating_session(
    endpoints: tuple[str, ...] = _YAHOO_ENDPOINTS,
    regions: tuple[str, ...] = DEFAULT_REGIONS,
    persistent: bool = True,
) -> Iterator[requests.Session]:
    """컨텍스트 매니저: 세션 사용 후 자동 정리.

    persistent=True (기본): AWS gateway를 영구 유지해서 다음 실행 시 재사용.

    사용 예:
        with ip_rotating_session() as session:
            ticker = yf.Ticker("AAPL", session=session)
            print(ticker.info)
    """
    session, gateways = create_rotating_session(
        endpoints=endpoints, regions=regions, persistent=persistent
    )
    try:
        yield session
    finally:
        shutdown_gateways(gateways, persistent=persistent)


def is_available() -> bool:
    """IP rotation 사용 가능 여부 (패키지 설치 + AWS creds). 실제 시작은 하지 않음."""
    try:
        _import_rotator()
    except IpRotationNotAvailable:
        return False
    # AWS creds 존재 여부 체크
    try:
        import boto3  # type: ignore

        sts = boto3.client("sts")
        sts.get_caller_identity()
        return True
    except Exception as exc:  # noqa: BLE001
        logger.debug("AWS credentials unavailable: %s", exc)
        return False
