from __future__ import annotations

from fastapi.testclient import TestClient

import eightmem.ui.app as ui_app
from eightmem.core.governance import create_approval_request, get_approval_request
from eightmem.ui.app import create_app


def test_telegram_webhook_to_user_scoped_ui_e2e(fake_home, monkeypatch):
    monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "123:abc")
    monkeypatch.setenv("TELEGRAM_WEBHOOK_SECRET", "secret-1")
    monkeypatch.setattr(
        ui_app,
        "send_telegram_message",
        lambda config, outgoing: {"ok": True, "result": {"chat_id": outgoing.chat_id, "text": outgoing.text}},
    )
    client = TestClient(create_app())

    headers = {"X-Telegram-Bot-Api-Secret-Token": "secret-1"}

    def _send(update_id: int, text: str) -> None:
        response = client.post(
            "/channels/telegram/webhook",
            headers=headers,
            json={
                "update_id": update_id,
                "message": {
                    "message_id": update_id,
                    "text": text,
                    "chat": {"id": 777},
                    "from": {"id": 123},
                },
            },
        )
        assert response.status_code == 200
        assert response.json()["ok"] is True

    _send(1, "reset memory")
    _send(2, "Remember: I prefer structured weekly plans with clear owners and deadlines")
    _send(3, "Remember: I care about product reliability more than flashy demos")
    _send(4, "Correct: do not assume I want long strategic essays")

    files = client.get("/files?user_id=123")
    assert files.status_code == 200
    assert "Prefers structured weekly plans with clear owners and deadlines." in files.text

    prefs_file = client.get("/files/PREFERENCES.md?user_id=123")
    assert prefs_file.status_code == 200
    assert "Prefers structured weekly plans with clear owners and deadlines." in prefs_file.text
    assert "Values product reliability more than flashy demos." in prefs_file.text

    corrections_file = client.get("/files/CORRECTIONS.md?user_id=123")
    assert corrections_file.status_code == 200
    assert "do not assume I want long strategic essays" in corrections_file.text

    mirror = client.get("/mirror?user_id=123")
    assert mirror.status_code == 200
    assert "Prefers structured weekly plans with clear owners and deadlines." in mirror.text
    assert "Values product reliability more than flashy demos." in mirror.text

    export = client.get("/export?user_id=123")
    assert export.status_code == 200
    assert "Prefers structured weekly plans with clear owners and deadlines." in export.text
    assert "Values product reliability more than flashy demos." in export.text
    assert "\n# PREFERENCES\n" not in export.text

    _send(5, "reset memory")
    recall = client.post(
        "/channels/telegram/webhook",
        headers=headers,
        json={
            "update_id": 6,
            "message": {
                "message_id": 6,
                "text": "What do you know about me",
                "chat": {"id": 777},
                "from": {"id": 123},
            },
        },
    )
    assert recall.status_code == 200
    assert "I don't have saved memory for you yet." in recall.json()["telegram"]["result"]["text"]


def test_telegram_compare_and_passport_e2e_expose_helper_keyboard(fake_home, monkeypatch):
    monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "123:abc")
    monkeypatch.setenv("TELEGRAM_WEBHOOK_SECRET", "secret-1")
    sent_messages: list[object] = []

    def _fake_send(config, outgoing):
        sent_messages.append(outgoing)
        return {"ok": True, "result": {"chat_id": outgoing.chat_id, "text": outgoing.text}}

    monkeypatch.setattr(ui_app, "send_telegram_message", _fake_send)
    client = TestClient(create_app())
    headers = {"X-Telegram-Bot-Api-Secret-Token": "secret-1"}

    def _send(update_id: int, text: str) -> object:
        response = client.post(
            "/channels/telegram/webhook",
            headers=headers,
            json={
                "update_id": update_id,
                "message": {
                    "message_id": update_id,
                    "text": text,
                    "chat": {"id": 777},
                    "from": {"id": 123},
                },
            },
        )
        assert response.status_code == 200
        assert response.json()["ok"] is True
        return sent_messages[-1]

    _send(1, "reset memory")
    _send(2, "Remember: keep answers concise")
    passport = _send(3, "/passport")
    compare = _send(4, "/compare Draft: write a founder update in my style")

    assert "Here's the memory I'm using for you:" in passport.text
    assert passport.reply_keyboard == [["/passport", "/compare"]]
    assert "Standard answer:" in compare.text
    assert "Answer shaped by what I know about you:" in compare.text
    assert compare.photo_path
    assert compare.photo_path.endswith(".png")
    assert compare.reply_keyboard == [["/passport", "/compare"]]


def test_telegram_guided_compare_e2e_reruns_after_context_capture(fake_home, monkeypatch):
    monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "123:abc")
    monkeypatch.setenv("TELEGRAM_WEBHOOK_SECRET", "secret-1")
    sent_messages: list[object] = []

    def _fake_send(config, outgoing):
        sent_messages.append(outgoing)
        return {"ok": True, "result": {"chat_id": outgoing.chat_id, "text": outgoing.text}}

    monkeypatch.setattr(ui_app, "send_telegram_message", _fake_send)
    client = TestClient(create_app())
    headers = {"X-Telegram-Bot-Api-Secret-Token": "secret-1"}

    def _send(update_id: int, text: str) -> object:
        response = client.post(
            "/channels/telegram/webhook",
            headers=headers,
            json={
                "update_id": update_id,
                "message": {
                    "message_id": update_id,
                    "text": text,
                    "chat": {"id": 777},
                    "from": {"id": 123},
                },
            },
        )
        assert response.status_code == 200
        assert response.json()["ok"] is True
        return sent_messages[-1]

    _send(1, "reset memory")
    guided = _send(2, "/compare Draft: write a founder update in my style")
    completed = _send(
        3,
        (
            "Working on: 8mem, an AI memory layer for visible, correctable, portable memory.\n"
            "Assistants should know: I care about execution speed, but not at the cost of stability.\n"
            "Do not assume: I want generic motivational language.\n"
            "Communication style: short, direct, structured as Progress / Risk / Next."
        ),
    )

    assert guided.action == "compare_guided_capture"
    assert "I saved your compare request: Draft: write a founder update in my style" in guided.text
    assert guided.photo_path is None
    assert completed.action == "compare_guided_capture_complete"
    assert "Context captured." in completed.text
    assert "Rerunning your compare now." in completed.text
    assert "8mem Compare" in completed.text
    assert completed.photo_path
    assert completed.photo_path.endswith(".png")


def test_telegram_callback_query_resolution_e2e(fake_home, monkeypatch):
    monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "123:abc")
    monkeypatch.setenv("TELEGRAM_WEBHOOK_SECRET", "secret-1")
    sent_messages: list[object] = []

    def _fake_send(config, outgoing):
        sent_messages.append(outgoing)
        return {"ok": True, "result": {"chat_id": outgoing.chat_id, "text": outgoing.text}}

    monkeypatch.setattr(ui_app, "send_telegram_message", _fake_send)
    client = TestClient(create_app())
    headers = {"X-Telegram-Bot-Api-Secret-Token": "secret-1"}

    response = client.post(
        "/channels/telegram/webhook",
        headers=headers,
        json={
            "update_id": 10,
            "message": {
                "message_id": 10,
                "text": "reset memory\nRemember: use emojis\nRemember: do not use emojis",
                "chat": {"id": 777},
                "from": {"id": 123},
            },
        },
    )
    assert response.status_code == 200
    assert sent_messages[-1].reply_keyboard == [["Use new", "Keep old"], ["Both are true", "Review later"]]

    callback = client.post(
        "/channels/telegram/webhook",
        headers=headers,
        json={
            "update_id": 11,
            "callback_query": {
                "id": "cbq-11",
                "data": "Use new",
                "from": {"id": 123},
                "message": {
                    "message_id": 10,
                    "chat": {"id": 777},
                },
            },
        },
    )
    assert callback.status_code == 200
    assert "I'll use this going forward" in sent_messages[-1].text
    assert "archived with a timestamp" in sent_messages[-1].text
    assert sent_messages[-1].callback_query_id == "cbq-11"


def test_telegram_approval_button_e2e(fake_home, monkeypatch):
    monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "123:abc")
    monkeypatch.setenv("TELEGRAM_WEBHOOK_SECRET", "secret-1")
    sent_messages: list[object] = []

    def _fake_send(config, outgoing):
        sent_messages.append(outgoing)
        return {"ok": True, "result": {"chat_id": outgoing.chat_id, "text": outgoing.text}}

    monkeypatch.setattr(ui_app, "send_telegram_message", _fake_send)
    client = TestClient(create_app())
    headers = {"X-Telegram-Bot-Api-Secret-Token": "secret-1"}
    approval = create_approval_request(
        user_id="123",
        action_type="email_send",
        summary="Send Phase 1 update to investor",
        payload={"to": "investor@example.com", "subject": "Phase 1 update"},
    )

    list_response = client.post(
        "/channels/telegram/webhook",
        headers=headers,
        json={
            "update_id": 20,
            "message": {
                "message_id": 20,
                "text": "/approvals",
                "chat": {"id": 777},
                "from": {"id": 123},
            },
        },
    )
    assert list_response.status_code == 200
    assert "Approval needed" in sent_messages[-1].text
    assert sent_messages[-1].reply_keyboard[0][0]["callback_data"] == f"approval:approved:{approval.approval_id}"

    approve_response = client.post(
        "/channels/telegram/webhook",
        headers=headers,
        json={
            "update_id": 21,
            "callback_query": {
                "id": "cbq-approval-21",
                "data": f"approval:approved:{approval.approval_id}",
                "from": {"id": 123},
                "message": {
                    "message_id": 20,
                    "chat": {"id": 777},
                },
            },
        },
    )

    assert approve_response.status_code == 200
    assert "Approved: Send email" in sent_messages[-1].text
    assert sent_messages[-1].callback_query_id == "cbq-approval-21"
    fetched = get_approval_request(approval.approval_id, user_id="123")
    assert fetched is not None
    assert fetched.status == "approved"
    assert fetched.resolved_by == "telegram"
