#!/usr/bin/env python3
"""
test_kiwoom_ws.py — 키움 WebSocket 시세 단독 검증 스크립트
=========================================================

봇 안 띄우고 ``kiwoom_ws.KiwoomWebSocketPriceCache`` 만 직접 띄워서
연결·로그인·등록·시세 수신이 정상인지 30~60초 안에 확인.

사용법
------

기본 (DB 키 자동 로드, 삼성전자 + SK하이닉스 30초 구독)::

    python3 test_kiwoom_ws.py

종목 직접 지정::

    python3 test_kiwoom_ws.py --codes 005930,000660,005380 --duration 60

장외에 띄워도 LOGIN/REG ack 까지 확인 가능 (시세는 안 오지만 인증 동작 검증).

출력 해석
---------

✅ LOGIN OK         → 키움 토큰·키 정상
✅ REG OK           → 종목 등록 성공
📈 005930 73900...  → 1초 1줄, 실시간 가격 수신 정상
⚠️ 가격 수신 0건    → 장외 또는 키움 서버 정책
❌ LOGIN 실패       → 키 / OpenAPI 신청 / 도메인 문제 (test_kiwoom_token.py 로 추가 진단)
"""
from __future__ import annotations

import argparse
import logging
import sys
import time
from pathlib import Path

SCRIPT_DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(SCRIPT_DIR))


def setup_logging(verbose: bool) -> None:
    fmt = "[%(asctime)s] [%(name)s] %(message)s"
    logging.basicConfig(
        level=logging.DEBUG if verbose else logging.INFO,
        format=fmt,
        datefmt="%H:%M:%S",
    )


def load_kiwoom_creds() -> tuple[str, str, bool]:
    """DB env_config 에서 키움 키 로드 (KIS_MOCK 따라 MOCK/REAL 자동 선택)."""
    from kis_ws import _get_kiwoom_creds  # type: ignore
    from database import TradeDB

    db = TradeDB()
    try:
        return _get_kiwoom_creds(db)
    finally:
        db.close()


def main() -> int:
    p = argparse.ArgumentParser(description="키움 WebSocket 시세 단독 검증")
    p.add_argument(
        "--codes",
        default="005930,000660",
        help="콤마 구분 종목코드 (기본: 삼성전자, SK하이닉스)",
    )
    p.add_argument(
        "--duration", type=int, default=30,
        help="구독 유지 시간(초). 기본 30",
    )
    p.add_argument("-v", "--verbose", action="store_true", help="DEBUG 로그")
    args = p.parse_args()

    setup_logging(args.verbose)
    logger = logging.getLogger("test_kiwoom_ws")

    codes = [c.strip() for c in args.codes.split(",") if c.strip()]
    if not codes:
        print("❌ --codes 비어있음")
        return 2

    print("=" * 70)
    print("🔍 키움 WS 단독 검증")
    print("=" * 70)

    # 키 로드
    try:
        app_key, app_secret, is_mock = load_kiwoom_creds()
    except Exception as e:
        print(f"❌ 키 로드 실패: {e}")
        return 1
    if not app_key or not app_secret:
        print("❌ 키움 키 미설정 (DB env_config 의 KIWOOM_APP_KEY_* 확인)")
        return 1
    print(f"  키움 키: {app_key[:8]}…{app_key[-4:]}  is_mock={is_mock}")
    print(f"  대상 종목: {codes}")
    print(f"  유지 시간: {args.duration}초")
    print()

    # WS 인스턴스
    from kiwoom_ws import KiwoomWebSocketPriceCache

    ws = KiwoomWebSocketPriceCache(app_key, app_secret, is_mock=is_mock)
    if not ws.start():
        print("❌ 키움 WS start() 실패")
        return 1

    # 종목 구독
    for code in codes:
        ws.subscribe(code)

    # 연결 + LOGIN 대기 (최대 15초)
    deadline = time.time() + 15
    while time.time() < deadline:
        if ws.is_connected():
            print(f"✅ LOGIN OK ({int(time.time() - (deadline - 15))}s)")
            break
        time.sleep(0.5)
    else:
        print("⚠️ LOGIN 미완료 (15초 timeout). 키움 토큰/네트워크 확인 필요")
        ws.stop()
        return 1

    # 가격 수신 모니터링
    print()
    print(f"📡 {args.duration}초간 시세 모니터링 (1초 간격 출력)...")
    end_ts = time.time() + args.duration
    last_dump_ts = 0.0
    received: dict = {}
    while time.time() < end_ts:
        now = time.time()
        if now - last_dump_ts >= 1.0:
            last_dump_ts = now
            for code in codes:
                d = ws.get_price(code, max_age_sec=10.0)
                if d:
                    px = d.get("stck_prpr", "?")
                    chg = d.get("prdy_ctrt", "?")
                    age = d.get("_age_ms", "?")
                    print(f"  📈 {code}  price={px}원  chg={chg}%  age={age}ms")
                    received[code] = received.get(code, 0) + 1
                else:
                    print(f"  ⏸  {code}  (no data — 장외/미수신)")
        time.sleep(0.2)

    # 종료
    print()
    print("─" * 70)
    print("종료. 수신 통계:")
    for code in codes:
        n = received.get(code, 0)
        mark = "✅" if n > 0 else "⚠️"
        print(f"  {mark} {code}: {n}회 수신")
    print("─" * 70)
    print()
    print("팁:")
    print("  • 모든 종목 0회면 장외 시간이거나 키움 정책 문제일 수 있음.")
    print("  • 장중에 0회면 → 키움 OpenAPI+ 신청 옵션 (실시간 시세 권한) 확인.")
    print("  • LOGIN 실패면 → test_kiwoom_token.py 로 토큰 발급 자체 진단.")

    ws.stop()
    return 0 if any(received.values()) else 1


if __name__ == "__main__":
    sys.exit(main())
