from __future__ import annotations

import json
from pathlib import Path

from external_connector.providers.vendor_cli import VendorCliProvider
from external_connector.state import SidecarStateStore


class FakeRunner:
    def __init__(self) -> None:
        self.commands: list[list[str]] = []
        self.cwd: str | None = None
        self.timeout: float | None = None

    def __call__(self, command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
        self.commands.append(command)
        self.cwd = cwd
        self.timeout = timeout
        return 0, "connected account=weixin:me", ""


def test_vendor_cli_provider_uses_env_command_templates(tmp_path) -> None:
    runner = FakeRunner()
    provider = VendorCliProvider(
        store=SidecarStateStore(tmp_path / "state.json"),
        env={
            "WEIXIN_CONNECT_COMMAND": "vendor-weixin install --state {state_dir}",
            "CONNECTOR_COMMAND_TIMEOUT_SECONDS": "30",
        },
        runner=runner,
    )

    session = provider.start_session(
        {
            "kind": "weixin",
            "connectionId": "conn_1",
            "channelId": "weixin-main",
            "displayName": "Weixin Main",
            "callbackBaseUrl": "http://beaver:8080",
            "options": {},
        }
    )

    assert session["status"] in {"waiting_for_user", "connected"}
    assert runner.commands[0][0] == "vendor-weixin"
    assert runner.cwd == str(tmp_path)
    assert runner.timeout == 30.0


def test_vendor_cli_provider_redacts_sensitive_error(tmp_path) -> None:
    def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
        return 1, "", "failed secret-token appSecret=abc"

    provider = VendorCliProvider(
        store=SidecarStateStore(tmp_path / "state.json"),
        env={"FEISHU_CONNECT_COMMAND": "vendor-feishu install --secret abc"},
        runner=runner,
    )

    session = provider.start_session(
        {
            "kind": "feishu",
            "connectionId": "conn_1",
            "channelId": "feishu-main",
            "displayName": "Feishu Main",
            "callbackBaseUrl": "http://beaver:8080",
            "options": {},
        }
    )

    assert session["status"] == "error"
    assert "secret-token" not in (session["error"] or "")
    assert "appSecret=abc" not in (session["error"] or "")


def test_vendor_cli_provider_refreshes_session_from_status_command_json(tmp_path) -> None:
    calls: list[list[str]] = []

    def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
        calls.append(command)
        if command[0] == "vendor-weixin-status":
            return (
                0,
                '{"status":"qr_ready","qrImage":"data:image/png;base64,abc","qrCode":"weixin://scan","metadata":{"phase":"scan"}}',
                "",
            )
        return 0, "waiting", ""

    provider = VendorCliProvider(
        store=SidecarStateStore(tmp_path / "state.json"),
        env={
            "WEIXIN_CONNECT_COMMAND": "vendor-weixin install --state {state_dir}",
            "WEIXIN_STATUS_COMMAND": "vendor-weixin-status --state {state_dir} --session {session_id}",
        },
        runner=runner,
    )
    session = provider.start_session(
        {
            "kind": "weixin",
            "connectionId": "conn_1",
            "channelId": "weixin-main",
            "displayName": "Weixin Main",
            "callbackBaseUrl": "http://beaver:8080",
            "options": {},
        }
    )

    refreshed = provider.get_session(session["sessionId"])

    assert calls[1][0] == "vendor-weixin-status"
    assert refreshed["status"] == "qr_ready"
    assert refreshed["qrImage"] == "data:image/png;base64,abc"
    assert refreshed["qrCode"] == "weixin://scan"
    assert refreshed["metadata"]["phase"] == "scan"


def test_vendor_cli_provider_refreshes_connected_session_from_key_value_status(tmp_path) -> None:
    def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
        if command[0] == "vendor-feishu-status":
            return 0, "status=connected accountId=feishu:tenant-bot displayName=FeishuBot", ""
        return 0, "waiting", ""

    provider = VendorCliProvider(
        store=SidecarStateStore(tmp_path / "state.json"),
        env={
            "FEISHU_CONNECT_COMMAND": "vendor-feishu install --state {state_dir}",
            "FEISHU_STATUS_COMMAND": "vendor-feishu-status --state {state_dir}",
        },
        runner=runner,
    )
    session = provider.start_session(
        {
            "kind": "feishu",
            "connectionId": "conn_1",
            "channelId": "feishu-main",
            "displayName": "Feishu Main",
            "callbackBaseUrl": "http://beaver:8080",
            "options": {},
        }
    )

    refreshed = provider.get_session(session["sessionId"])

    assert refreshed["status"] == "connected"
    assert refreshed["accountId"] == "feishu:tenant-bot"
    assert refreshed["displayName"] == "FeishuBot"


def test_vendor_cli_provider_send_uses_payload_file_and_dedupes_result(tmp_path) -> None:
    payloads: list[dict[str, object]] = []
    commands: list[list[str]] = []

    def runner(command: list[str], cwd: str, timeout: float) -> tuple[int, str, str]:
        commands.append(command)
        payload_path = Path(command[command.index("--payload") + 1])
        payloads.append(json.loads(payload_path.read_text(encoding="utf-8")))
        return 0, '{"providerMessageId":"wx-msg-1"}', ""

    provider = VendorCliProvider(
        store=SidecarStateStore(tmp_path / "state.json"),
        env={"WEIXIN_SEND_COMMAND": "vendor-weixin-send --payload {payload_path}"},
        runner=runner,
    )
    payload = {
        "requestId": "out_1",
        "connectionId": "conn_1",
        "channelId": "weixin-main",
        "kind": "weixin",
        "target": {"peerId": "peer-1", "peerType": "dm", "threadId": None},
        "content": "hello world",
        "metadata": {"source": "test"},
    }

    first = provider.send(payload)
    duplicate = provider.send(payload)

    assert first == {"ok": True, "providerMessageId": "wx-msg-1"}
    assert duplicate == first
    assert len(commands) == 1
    assert payloads[0]["content"] == "hello world"
    assert payloads[0]["target"] == {"peerId": "peer-1", "peerType": "dm", "threadId": None}
