import os
import sqlite3
import pytest
from fastapi.testclient import TestClient

from app.screener.schema import ensure_screener_schema
from app.db import init_db


@pytest.fixture(autouse=True)
def isolated_db_and_auth(tmp_path, monkeypatch):
    db_path = tmp_path / "stock.db"
    # 기본 stock DB 스키마
    monkeypatch.setenv("STOCK_DB_PATH", str(db_path))
    init_db()
    # screener 스키마 (news_sentiment, krx_master 등)
    c = sqlite3.connect(db_path)
    ensure_screener_schema(c)
    c.close()
    # WEBAI_API_KEY 활성화
    monkeypatch.setenv("WEBAI_API_KEY", "test-secret")


@pytest.fixture
def client():
    from app.main import app
    return TestClient(app)


HEADERS_OK = {"X-WebAI-Key": "test-secret"}


def _seed_portfolio(broker="키움", ticker="005930", name="삼성전자",
                    quantity=100, avg_price=75000.0, purchase_price=75500.0):
    from app.db import add_portfolio_item
    return add_portfolio_item(broker, ticker, name, quantity, avg_price,
                              purchase_price=purchase_price)


def test_webai_portfolio_normal_response_includes_pnl_pct(client, monkeypatch):
    _seed_portfolio()

    # current_price 모킹 — profit_rate 4.67% 만들기
    from app import main
    monkeypatch.setattr(
        main, "get_current_prices_detail",
        lambda tickers: {"005930": {"price": 78500.0, "session": "REGULAR", "as_of": "2026-05-15T15:30:00"}}
    )

    r = client.get("/api/webai/portfolio", headers=HEADERS_OK)
    assert r.status_code == 200
    body = r.json()
    assert len(body["holdings"]) == 1
    h = body["holdings"][0]
    assert h["pnl_pct"] is not None
    assert abs(h["pnl_pct"] - 0.0467) < 0.0005  # 0.0467 ± rounding


def test_webai_portfolio_summary_has_total_pnl_pct(client, monkeypatch):
    _seed_portfolio()
    from app import main
    monkeypatch.setattr(
        main, "get_current_prices_detail",
        lambda tickers: {"005930": {"price": 78500.0, "session": "REGULAR", "as_of": "x"}}
    )

    r = client.get("/api/webai/portfolio", headers=HEADERS_OK)
    body = r.json()
    assert "total_pnl_pct" in body["summary"]
    assert abs(body["summary"]["total_pnl_pct"] - 0.0467) < 0.0005


def test_webai_portfolio_pnl_pct_matches_profit_rate_divided_100(client, monkeypatch):
    _seed_portfolio()
    from app import main
    monkeypatch.setattr(
        main, "get_current_prices_detail",
        lambda tickers: {"005930": {"price": 78500.0, "session": "REGULAR", "as_of": "x"}}
    )

    r = client.get("/api/webai/portfolio", headers=HEADERS_OK)
    h = r.json()["holdings"][0]
    assert h["pnl_pct"] == round(h["profit_rate"] / 100, 6)


def test_webai_portfolio_missing_key_returns_401(client):
    r = client.get("/api/webai/portfolio")
    assert r.status_code == 401
    assert "X-WebAI-Key" in r.json()["detail"]


def _seed_news_sentiment(date_str: str, rows: list[tuple]):
    """rows: list of (ticker, score_raw, reason, news_count)."""
    db_path = os.environ["STOCK_DB_PATH"]
    c = sqlite3.connect(db_path)
    for ticker, score, reason, news_count in rows:
        c.execute(
            "INSERT OR REPLACE INTO news_sentiment "
            "(ticker, date, score_raw, reason, news_count, source) "
            "VALUES (?, ?, ?, ?, ?, 'articles')",
            (ticker, date_str, score, reason, news_count)
        )
    c.commit()
    c.close()


def _seed_krx_master(rows: list[tuple]):
    """rows: list of (ticker, name)."""
    db_path = os.environ["STOCK_DB_PATH"]
    c = sqlite3.connect(db_path)
    import datetime as dt
    now = dt.datetime.utcnow().isoformat()
    for ticker, name in rows:
        c.execute(
            "INSERT OR REPLACE INTO krx_master "
            "(ticker, name, market, market_cap, updated_at) VALUES (?, ?, 'KOSPI', 0, ?)",
            (ticker, name, now)
        )
    c.commit()
    c.close()


def test_webai_news_sentiment_returns_latest_date_when_no_param(client):
    _seed_krx_master([("005930", "삼성전자"), ("000660", "SK하이닉스")])
    _seed_news_sentiment("2026-05-14", [("005930", 5.0, "old", 5)])
    _seed_news_sentiment("2026-05-15", [
        ("005930", 6.2, "HBM 양산 가시화", 12),
        ("000660", 5.5, "PPI 우려에도 강세", 8),
    ])

    r = client.get("/api/webai/news-sentiment", headers=HEADERS_OK)
    assert r.status_code == 200
    body = r.json()
    assert body["date"] == "2026-05-15"
    assert body["count"] == 2
    # sorted by score DESC
    assert body["items"][0]["ticker"] == "005930"
    assert body["items"][0]["score"] == 6.2
    assert body["items"][0]["name"] == "삼성전자"
    assert body["items"][0]["reason"] == "HBM 양산 가시화"


def test_webai_news_sentiment_filters_by_date_param(client):
    _seed_krx_master([("005930", "삼성전자")])
    _seed_news_sentiment("2026-05-14", [("005930", 5.0, "yesterday", 5)])
    _seed_news_sentiment("2026-05-15", [("005930", 6.2, "today", 12)])

    r = client.get("/api/webai/news-sentiment?date=2026-05-14", headers=HEADERS_OK)
    body = r.json()
    assert body["date"] == "2026-05-14"
    assert body["count"] == 1
    assert body["items"][0]["reason"] == "yesterday"


def test_webai_news_sentiment_empty_table_returns_count_zero(client):
    r = client.get("/api/webai/news-sentiment", headers=HEADERS_OK)
    body = r.json()
    assert body["date"] is None
    assert body["count"] == 0
    assert body["items"] == []


def test_webai_news_sentiment_items_sorted_by_score_desc(client):
    _seed_krx_master([("A", "A주"), ("B", "B주"), ("C", "C주")])
    _seed_news_sentiment("2026-05-15", [
        ("A", 1.0, "low", 1),
        ("B", 9.0, "high", 1),
        ("C", 5.0, "mid", 1),
    ])

    r = client.get("/api/webai/news-sentiment", headers=HEADERS_OK)
    items = r.json()["items"]
    assert [i["score"] for i in items] == [9.0, 5.0, 1.0]


def test_webai_401_response_has_no_payload_leak(client):
    """인증 실패 응답에는 portfolio/sentiment 데이터가 없어야 한다."""
    _seed_portfolio()
    r = client.get("/api/webai/portfolio")  # 헤더 없음
    assert r.status_code == 401
    body = r.json()
    assert "holdings" not in body
    assert "cash" not in body
    assert "summary" not in body


def test_webai_503_when_env_missing(client, monkeypatch):
    """WEBAI_API_KEY env 미설정 시 503, 다른 endpoint 영향 없음."""
    monkeypatch.delenv("WEBAI_API_KEY", raising=False)

    r1 = client.get("/api/webai/portfolio", headers={"X-WebAI-Key": "anything"})
    assert r1.status_code == 503

    # 기존 endpoint 무영향 — /api/portfolio 는 200 (빈 portfolio)
    r2 = client.get("/api/portfolio")
    assert r2.status_code == 200


def test_webai_wrong_key_returns_401(client):
    r = client.get("/api/webai/portfolio", headers={"X-WebAI-Key": "wrong"})
    assert r.status_code == 401


def test_webai_news_sentiment_unknown_date_returns_empty(client):
    r = client.get("/api/webai/news-sentiment?date=1999-01-01", headers=HEADERS_OK)
    assert r.status_code == 200
    body = r.json()
    assert body["count"] == 0
    assert body["items"] == []
