import sys
import types

import pytest

from mnemosynecore import secrets as secrets_mod
from mnemosynecore import superset as superset_mod


def test_superset_request_success(monkeypatch):
    class Resp:
        def raise_for_status(self):
            return None

        def json(self):
            return {"ok": True}

    captured = {}
    monkeypatch.setattr(
        superset_mod,
        "get_secret",
        lambda conn: {"host": "https://s.example/", "password": "TOKEN"},
    )
    monkeypatch.setattr(
        superset_mod.requests,
        "request",
        lambda method, url, json=None, headers=None: (
            captured.update({"call": (method, url, json, headers)}) or Resp()
        ),
    )

    out = superset_mod.superset_request(
        endpoint="/api/v1/me",
        method="POST",
        payload={"x": 1},
        vault_conn_id="SUP",
    )
    assert out == {"ok": True}
    method, url, payload, headers = captured["call"]
    assert method == "POST"
    assert url == "https://s.example/api/v1/me"
    assert payload == {"x": 1}
    assert headers["Authorization"] == "Bearer TOKEN"


def test_superset_request_raise_for_status(monkeypatch):
    class Resp:
        def raise_for_status(self):
            raise RuntimeError("bad status")

    monkeypatch.setattr(
        superset_mod,
        "get_secret",
        lambda conn: {"host": "https://s.example/", "password": "TOKEN"},
    )
    monkeypatch.setattr(superset_mod.requests, "request", lambda *args, **kwargs: Resp())
    with pytest.raises(RuntimeError, match="bad status"):
        superset_mod.superset_request(endpoint="/x", vault_conn_id="SUP")


def test_get_superset_client_via_superset_api(monkeypatch):
    captured = {}

    def fake_superset_api(**kwargs):
        captured["kwargs"] = kwargs
        return "CLIENT"

    fake_pkg = types.ModuleType("superset_o3_api_lib")
    fake_pkg.superset_o3_api_lib = types.SimpleNamespace(superset_api=fake_superset_api)
    monkeypatch.setitem(sys.modules, "superset_o3_api_lib", fake_pkg)

    monkeypatch.setattr(
        secrets_mod,
        "resolve_secret",
        lambda conn_id, dir_path=None: {
            "host": "https://ss.o3.ru",
            "login": "svc_user",
            "password": "svc_pwd",
            "extra": '{"auth_provider":"ldap"}',
        },
    )

    client = superset_mod.get_superset_client(superset_conn="SUP")
    assert client == "CLIENT"
    assert captured["kwargs"]["username"] == "svc_user"
    assert captured["kwargs"]["auth_provider"] == "ldap"


def test_get_superset_client_fallback_legacy(monkeypatch):
    calls = {}

    class FakeOAuth:
        def __init__(self, **kwargs):
            calls["auth"] = kwargs

    class FakeClient:
        def __init__(self, auth):
            calls["client_auth"] = auth

    fake_pkg = types.ModuleType("superset_o3_api_lib")
    fake_pkg.SupersetAPIClient = FakeClient
    fake_auth = types.ModuleType("superset_o3_api_lib.auth")
    fake_auth.PasswordOAuthFlow = FakeOAuth
    monkeypatch.setitem(sys.modules, "superset_o3_api_lib", fake_pkg)
    monkeypatch.setitem(sys.modules, "superset_o3_api_lib.auth", fake_auth)

    client = superset_mod.get_superset_client(
        superset_conn={
            "host": "https://superset.local",
            "login": "u",
            "password": "p",
            "schema": "client_id",
            "extra": {"client_secret": "sec"},
        }
    )

    assert isinstance(client, FakeClient)
    assert calls["auth"]["superset_host"] == "https://superset.local"
    assert calls["auth"]["client_secret"] == "sec"


def test_superset_dashboard_thumbnail_new_api(monkeypatch):
    class FakeClient:
        def dashboard_thumbnail(self, **kwargs):
            self.kwargs = kwargs
            return b"PNG"

    fake_client = FakeClient()
    monkeypatch.setattr(superset_mod, "get_superset_client", lambda **kwargs: fake_client)

    out = superset_mod.superset_dashboard_thumbnail(
        superset_conn="SUP",
        dashboard_name="Main dashboard",
        dashboard_url="https://ss.o3.ru/superset/dashboard/p/abc/",
        thumb_size=(2048, 1536),
        window_size="2048, 1536",
    )
    assert out == b"PNG"
    assert fake_client.kwargs["dashboard_name"] == "Main dashboard"
    assert fake_client.kwargs["thumb_size"] == "2048,1536"


def test_superset_dashboard_thumbnail_legacy_api(monkeypatch):
    class FakeClient:
        def dashboard_screenshot(self, **kwargs):
            self.kwargs = kwargs
            return b"LEGACY"

    fake_client = FakeClient()
    monkeypatch.setattr(superset_mod, "get_superset_client", lambda **kwargs: fake_client)

    out = superset_mod.superset_dashboard_thumbnail(
        superset_conn="SUP",
        dashboard_id=77,
        thumb_size="800,600",
        window_size=(1600, 1200),
    )
    assert out == b"LEGACY"
    assert fake_client.kwargs["dashboard_id"] == 77
    assert fake_client.kwargs["thumb_size"] == (800, 600)


def test_superset_chart_thumbnail(monkeypatch):
    class FakeClient:
        def chart_thumbnail(self, **kwargs):
            self.kwargs = kwargs
            return b"CHART"

    fake_client = FakeClient()
    monkeypatch.setattr(superset_mod, "get_superset_client", lambda **kwargs: fake_client)

    out = superset_mod.superset_chart_thumbnail(
        superset_conn="SUP",
        chart_id=31729,
        thumb_size="1200,800",
    )
    assert out == b"CHART"
    assert fake_client.kwargs["chart_id"] == 31729


def test_superset_screenshot_dashboard_saves_files(monkeypatch, tmp_path):
    monkeypatch.setattr(superset_mod, "superset_dashboard_thumbnail", lambda **kwargs: b"PNGDATA")

    out = superset_mod.superset_screenshot_dashboard(
        conn_id="SUP",
        dashboards=[
            {"dashboard_name": "Sales main"},
            {"name": "Filters tab", "file_name": "custom_name"},
        ],
        output_dir=str(tmp_path),
    )

    assert len(out) == 2
    assert (tmp_path / "1_Sales_main.png").read_bytes() == b"PNGDATA"
    assert (tmp_path / "2_custom_name.png").read_bytes() == b"PNGDATA"


def test_superset_screenshot_charts_saves_files(monkeypatch, tmp_path):
    monkeypatch.setattr(superset_mod, "superset_chart_thumbnail", lambda **kwargs: b"CHARTDATA")

    out = superset_mod.superset_screenshot_charts(
        conn_id="SUP",
        charts=[{"chart_id": 11}, {"id": 22, "file_name": "finance_chart"}],
        output_dir=str(tmp_path),
    )

    assert len(out) == 2
    assert (tmp_path / "1_chart_11.png").read_bytes() == b"CHARTDATA"
    assert (tmp_path / "2_finance_chart.png").read_bytes() == b"CHARTDATA"


def test_send_superset_dashboard_screenshot(monkeypatch):
    class FakeFiles:
        def upload_file(self, channel_id, files):
            self.channel_id = channel_id
            self.files = files
            return {"file_infos": [{"id": "F1"}]}

    class FakePosts:
        def create_post(self, options):
            self.options = options
            return {"id": "P1"}

    class FakeDriver:
        def __init__(self):
            self.files = FakeFiles()
            self.posts = FakePosts()

    driver = FakeDriver()
    monkeypatch.setattr(superset_mod, "_get_mattermost_driver", lambda bot_id: driver)
    monkeypatch.setattr(superset_mod, "superset_dashboard_thumbnail", lambda **kwargs: b"PNG")

    out = superset_mod.send_superset_dashboard_screenshot(
        channel_id="CH1",
        bot_id="MM_BOT",
        superset_conn="SUP",
        dashboard_name="Revenue",
        text="Daily snapshot",
    )

    assert out["file_id"] == "F1"
    assert out["post_id"] == "P1"
    assert driver.posts.options["file_ids"] == ["F1"]
    assert driver.posts.options["message"] == "Daily snapshot"


def test_send_superset_chart_screenshot(monkeypatch):
    class FakeFiles:
        def upload_file(self, channel_id, files):
            return {"file_infos": [{"id": "F2"}]}

    class FakePosts:
        def create_post(self, options):
            return {"id": "P2"}

    class FakeDriver:
        def __init__(self):
            self.files = FakeFiles()
            self.posts = FakePosts()

    monkeypatch.setattr(superset_mod, "_get_mattermost_driver", lambda bot_id: FakeDriver())
    monkeypatch.setattr(superset_mod, "superset_chart_thumbnail", lambda **kwargs: b"PNG")

    out = superset_mod.send_superset_chart_screenshot(
        channel_id="CH_CHART",
        bot_id="MM_BOT",
        superset_conn="SUP",
        chart_id=123,
    )
    assert out["file_id"] == "F2"
    assert out["post_id"] == "P2"


def test_send_bulk_dashboard_and_chart(monkeypatch):
    monkeypatch.setattr(
        superset_mod,
        "send_superset_dashboard_screenshot",
        lambda **kwargs: {"channel_id": kwargs["channel_id"], "file_id": "FD", "post_id": "PD", "file_name": "a.png"},
    )
    monkeypatch.setattr(
        superset_mod,
        "send_superset_chart_screenshot",
        lambda **kwargs: {"channel_id": kwargs["channel_id"], "file_id": "FC", "post_id": "PC", "file_name": "b.png"},
    )

    dashboards = superset_mod.send_superset_dashboards_to_channels(
        bot_id="MM",
        superset_conn="SUP",
        dashboards=[{"dashboard_name": "Main", "channel_id": "D1"}],
    )
    charts = superset_mod.send_superset_charts_to_channels(
        bot_id="MM",
        superset_conn="SUP",
        charts=[{"chart_id": 1, "channel_id": "C1"}],
    )

    assert dashboards[0]["file_id"] == "FD"
    assert charts[0]["file_id"] == "FC"


def test_superset_chart_thumbnail_test_supports_creds_path(monkeypatch, tmp_path):
    creds_file = tmp_path / "superset_creds.json"
    creds_file.write_text(
        '{"host":"https://ss.local","login":"u","password":"p"}',
        encoding="utf-8",
    )
    captured = {}

    monkeypatch.setattr(
        superset_mod,
        "superset_chart_thumbnail",
        lambda **kwargs: captured.update(kwargs) or b"PNG",
    )

    out = superset_mod.superset_chart_thumbnail_test(
        superset_conn="SUP_CONN",
        chart_id=5,
        creds_path=str(creds_file),
    )
    assert out == b"PNG"
    assert captured["superset_conn"]["host"] == "https://ss.local"


def test_superset_link_builders():
    dashboard_url = superset_mod.superset_dashboard_url(
        superset_conn={"host": "https://ss.local"},
        dashboard_id=123,
    )
    chart_url = superset_mod.superset_chart_url(
        superset_conn={"host": "https://ss.local"},
        chart_id=456,
    )
    assert dashboard_url.endswith("/superset/dashboard/123/")
    assert "slice_id=456" in chart_url

    d_link = superset_mod.superset_dashboard_link(
        superset_conn={"host": "https://ss.local"},
        dashboard_id=123,
        dashboard_name="Main",
    )
    c_link = superset_mod.superset_chart_link(
        superset_conn={"host": "https://ss.local"},
        chart_id=456,
        chart_name="Chart A",
    )
    assert d_link == "[Main](https://ss.local/superset/dashboard/123/)"
    assert c_link == "[Chart A](https://ss.local/superset/explore/?slice_id=456)"


def test_send_superset_dashboard_link(monkeypatch):
    captured = {}
    monkeypatch.setattr(
        __import__("mnemosynecore.mattermost", fromlist=["post_message"]),
        "post_message",
        lambda **kwargs: captured.update(kwargs) or {"post_id": "P1", "root_id": kwargs.get("root_id")},
    )

    out = superset_mod.send_superset_dashboard_link(
        channel_id="CH",
        bot_id="BOT",
        superset_conn={"host": "https://ss.local"},
        dashboard_id=11,
        dashboard_name="Daily KPI",
        text="Header",
        root_id="ROOT1",
    )
    assert out["post_id"] == "P1"
    assert out["root_id"] == "ROOT1"
    assert "[Daily KPI](https://ss.local/superset/dashboard/11/)" in captured["text"]


def test_send_superset_chart_link(monkeypatch):
    captured = {}
    monkeypatch.setattr(
        __import__("mnemosynecore.mattermost", fromlist=["post_message"]),
        "post_message",
        lambda **kwargs: captured.update(kwargs) or {"post_id": "P2", "root_id": kwargs.get("root_id")},
    )

    out = superset_mod.send_superset_chart_link(
        channel_id="CH",
        bot_id="BOT",
        superset_conn={"host": "https://ss.local"},
        chart_id=22,
        chart_name="Orders",
    )
    assert out["post_id"] == "P2"
    assert "[Orders](https://ss.local/superset/explore/?slice_id=22)" in captured["text"]


def test_send_superset_dashboard_links_to_thread(monkeypatch):
    calls = []

    def fake_send_dashboard_link(**kwargs):
        calls.append(kwargs)
        index = len(calls)
        return {
            "post_id": "MAIN" if index == 1 else f"T{index}",
            "root_id": kwargs.get("root_id"),
            "link": "L",
        }

    monkeypatch.setattr(superset_mod, "send_superset_dashboard_link", fake_send_dashboard_link)
    monkeypatch.setattr(
        __import__("mnemosynecore.mattermost", fromlist=["send_thread_messages"]),
        "send_thread_messages",
        lambda **kwargs: {"sent": [{"post_id": "X"}], "failed": []},
    )

    out = superset_mod.send_superset_dashboard_links_to_thread(
        channel_id="CH",
        bot_id="BOT",
        superset_conn="SUP",
        dashboards=[
            {"dashboard_name": "Main", "id": 1},
            {"dashboard_name": "Thread", "id": 2},
        ],
        header_text="Weekly",
        thread_messages=["plain text in thread"],
    )
    assert out["main_post_id"] == "MAIN"
    assert out["root_id"] == "MAIN"
    assert len(out["links_sent"]) == 2
    assert calls[1]["root_id"] == "MAIN"


def test_superset_screenshot_to_file_helpers(monkeypatch, tmp_path):
    monkeypatch.setattr(superset_mod, "superset_dashboard_thumbnail", lambda **kwargs: b"DASH")
    monkeypatch.setattr(superset_mod, "superset_chart_thumbnail", lambda **kwargs: b"CHART")

    dash_path = superset_mod.superset_dashboard_screenshot_to_file(
        superset_conn="SUP",
        dashboard_name="Main",
        output_path=str(tmp_path / "dash.png"),
    )
    chart_path = superset_mod.superset_chart_screenshot_to_file(
        superset_conn="SUP",
        chart_id=12,
        output_path=str(tmp_path / "chart.png"),
    )
    assert (tmp_path / "dash.png").read_bytes() == b"DASH"
    assert (tmp_path / "chart.png").read_bytes() == b"CHART"
    assert dash_path.endswith("dash.png")
    assert chart_path.endswith("chart.png")


def test_send_superset_dashboard_permalink_screenshot(monkeypatch):
    captured = {}
    monkeypatch.setattr(
        superset_mod,
        "send_superset_dashboard_screenshot",
        lambda **kwargs: captured.update(kwargs) or {"post_id": "P1", "file_id": "F1"},
    )

    out = superset_mod.send_superset_dashboard_permalink_screenshot(
        channel_id="CH",
        bot_id="BOT",
        superset_conn="SUP",
        dashboard_url="https://ss.local/superset/dashboard/p/abc/?native_filters_key=xyz",
        dashboard_name="Filtered board",
        text="message",
    )
    assert out["post_id"] == "P1"
    assert captured["dashboard_url"].startswith("https://ss.local/superset/dashboard/p/abc/")
    assert "[Filtered board](https://ss.local/superset/dashboard/p/abc/?native_filters_key=xyz)" in captured["text"]
