"""Chat modülü testleri — widget CRUD, public widget, session, mesaj, panel, izolasyon."""
import pytest

from tests.conftest import unique_email


async def _auth_headers(client) -> dict:
    r = await client.post(
        "/api/auth/register",
        json={"name": "Shop", "email": unique_email(), "password": "secret123"},
    )
    return {"Authorization": f"Bearer {r.json()['data']['token']['access_token']}"}


async def _make_widget(client, headers, **kwargs) -> dict:
    body = {"name": "Ana Site", **kwargs}
    r = await client.post("/api/widgets", headers=headers, json=body)
    return r.json()["data"]


# ============================================================
# PANEL WIDGET CRUD
# ============================================================


@pytest.mark.asyncio
async def test_widget_create_list_get_update(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    assert w["api_key"].startswith("fvy_live_")
    wid = w["id"]

    lst = await client.get("/api/widgets", headers=h)
    assert any(x["id"] == wid for x in lst.json()["data"])

    g = await client.get(f"/api/widgets/{wid}", headers=h)
    assert g.json()["data"]["id"] == wid

    upd = await client.put(
        f"/api/widgets/{wid}", headers=h, json={"is_online": False, "name": "Yeni"}
    )
    assert upd.json()["data"]["is_online"] is False
    assert upd.json()["data"]["name"] == "Yeni"


@pytest.mark.asyncio
async def test_widget_requires_auth(client):
    assert (await client.get("/api/widgets")).status_code == 401


# ============================================================
# PUBLIC WIDGET (api_key)
# ============================================================


@pytest.mark.asyncio
async def test_public_settings_no_domain_restriction(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    r = await client.get(f"/api/widget/{w['api_key']}/settings")
    assert r.status_code == 200
    data = r.json()["data"]
    assert data["widget_id"] == w["id"]
    assert "welcome_message" in data["settings"]


@pytest.mark.asyncio
async def test_settings_unknown_api_key_404(client):
    r = await client.get("/api/widget/fvy_live_bilinmeyen/settings")
    assert r.status_code == 404


@pytest.mark.asyncio
async def test_domain_validation(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h, allowed_domains=["ornek.com"])
    key = w["api_key"]

    # yanlış domain → 403
    bad = await client.get(
        f"/api/widget/{key}/settings", headers={"Origin": "https://baska.com"}
    )
    assert bad.status_code == 403

    # doğru domain → 200
    good = await client.get(
        f"/api/widget/{key}/settings", headers={"Origin": "https://ornek.com"}
    )
    assert good.status_code == 200


# ============================================================
# SESSION + MESSAGE
# ============================================================


async def _open_session(client, api_key) -> str:
    r = await client.post(
        f"/api/widget/{api_key}/session/create",
        json={"visitor_name": "Ayşe", "kvkk_consent": True},
    )
    return r.json()["data"]["session_token"]


@pytest.mark.asyncio
async def test_session_message_flow_turkish(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    token = await _open_session(client, w["api_key"])

    msg = "Kırmızı tişört var mı? Şişe boyutları nelerdir?"
    send = await client.post(
        "/api/widget/message/send", json={"session_token": token, "message": msg}
    )
    assert send.status_code == 201
    assert send.json()["data"]["message"] == msg
    assert send.json()["data"]["sender_type"] == "visitor"

    hist = await client.get(f"/api/widget/message/history?session_token={token}")
    assert hist.status_code == 200
    assert hist.json()["data"][0]["message"] == msg


@pytest.mark.asyncio
async def test_closed_session_rejects_message(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    token = await _open_session(client, w["api_key"])

    await client.post(f"/api/widget/session/close?session_token={token}")
    r = await client.post(
        "/api/widget/message/send", json={"session_token": token, "message": "selam"}
    )
    assert r.status_code == 422
    assert r.json()["error"]["code"] == "VALIDATION_FAILED"


@pytest.mark.asyncio
async def test_nps_submit(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    token = await _open_session(client, w["api_key"])
    r = await client.post(
        "/api/widget/nps", json={"session_token": token, "score": 9, "comment": "Harika"}
    )
    assert r.status_code == 204


@pytest.mark.asyncio
async def test_message_unknown_token_404(client):
    r = await client.post(
        "/api/widget/message/send", json={"session_token": "yok", "message": "x"}
    )
    assert r.status_code == 404


# ============================================================
# PANEL SESSIONS
# ============================================================


@pytest.mark.asyncio
async def test_panel_session_detail_and_operator(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    token = await _open_session(client, w["api_key"])
    await client.post(
        "/api/widget/message/send", json={"session_token": token, "message": "merhaba"}
    )

    lst = await client.get("/api/sessions", headers=h)
    assert len(lst.json()["data"]) == 1
    sid = lst.json()["data"][0]["id"]

    detail = await client.get(f"/api/sessions/{sid}", headers=h)
    assert detail.json()["data"]["session"]["id"] == sid
    assert len(detail.json()["data"]["messages"]) == 1

    # devral
    tk = await client.post(f"/api/sessions/{sid}/takeover", headers=h)
    assert tk.json()["data"]["status"] == "escalated"

    # operatör mesajı
    op = await client.post(
        f"/api/sessions/{sid}/message", headers=h, json={"message": "Ben operatörüm"}
    )
    assert op.json()["data"]["sender_type"] == "operator"


@pytest.mark.asyncio
async def test_session_tenant_isolation(client):
    h_a = await _auth_headers(client)
    h_b = await _auth_headers(client)
    w = await _make_widget(client, h_a)
    await _open_session(client, w["api_key"])

    lst_a = await client.get("/api/sessions", headers=h_a)
    sid = lst_a.json()["data"][0]["id"]

    # B tenant A'nın oturumunu göremez
    assert (await client.get(f"/api/sessions/{sid}", headers=h_b)).status_code == 404
    assert (await client.get("/api/sessions", headers=h_b)).json()["data"] == []


# ============================================================
# WIDGET PRODUCT SEARCH (Adım 3'ten ertelenen — api_key)
# ============================================================


@pytest.mark.asyncio
async def test_widget_product_search(client):
    h = await _auth_headers(client)
    w = await _make_widget(client, h)
    await client.post(
        "/api/products", headers=h,
        json={"title": "Kırmızı Tişört", "price": "199", "stock_quantity": 5},
    )
    await client.post(
        "/api/products", headers=h,
        json={"title": "Mavi Pantolon", "price": "299", "stock_quantity": 3},
    )

    r = await client.get(f"/api/widget/{w['api_key']}/products/search?q=tişört")
    assert r.status_code == 200
    titles = [p["title"] for p in r.json()["data"]]
    assert "Kırmızı Tişört" in titles
    assert "Mavi Pantolon" not in titles

    # max_price filtresi
    r2 = await client.get(f"/api/widget/{w['api_key']}/products/search?max_price=200")
    prices = [float(p["price"]) for p in r2.json()["data"]]
    assert all(p <= 200 for p in prices)
