import datetime
import json
from pathlib import Path

import pytest
from typer.testing import CliRunner
from qrm.query_commands import query
from qrm.client import LoginState, QrmClientError
import typer

_test_app = typer.Typer()
_test_app.command()(query)
runner = CliRunner()


def test_query_command_calls_api(monkeypatch, tmp_path):
    """query should load stored credentials and print the API response for today."""
    state, config_path = make_fake_state(tmp_path)
    captured = {}

    class FakeClient:
        def __init__(self, base_url: str, verify_tls: bool) -> None:
            captured["base_url"] = base_url
            captured["verify_tls"] = verify_tls

        def export_sql(self, token, query, format, parameters):
            captured["token"] = token
            captured["query"] = query
            captured["format"] = format
            captured["parameters"] = parameters
            return {"result": "ok", "parameters": parameters}

    # Patch QrmClient for testability
    import qrm.query_commands as query_commands

    monkeypatch.setattr(query_commands, "QrmClient", FakeClient)

    # Simulate today
    today = datetime.datetime.now(datetime.timezone.utc)
    start = today.replace(hour=0, minute=0, second=0, microsecond=0)
    stop = today.replace(hour=23, minute=59, second=59, microsecond=0)

    result = runner.invoke(
        _test_app,
        [
            "--config-path",
            str(config_path),
            "--output",
            "json",
        ],
    )

    assert result.exit_code == 0
    out = json.loads(result.stdout)
    assert out["result"] == "ok"
    assert captured["token"] == "TOKEN123"
    assert "tResultSet" in captured["query"]
    assert captured["format"] == "json"
    # Check that parameters match today's date
    assert "start" in captured["parameters"]
    assert "stop" in captured["parameters"]


def make_fake_state(tmp_path):
    state = LoginState(
        token="TOKEN123",
        username="alice",
        base_url="https://qrm.local/api",
        verify_tls=True,
    )
    config_path = tmp_path / "login.json"
    config_path.write_text(state.model_dump_json())
    return state, config_path


class FakeClient:
    def __init__(self, base_url: str, verify_tls: bool) -> None:
        self.base_url = base_url
        self.verify_tls = verify_tls
        self.called = {}

    def export_sql(self, token, query, format, parameters):
        self.called = {
            "token": token,
            "query": query,
            "format": format,
            "parameters": parameters,
        }
        return {"result": "ok", "parameters": parameters}


def test_query_success(monkeypatch, tmp_path):
    state, config_path = make_fake_state(tmp_path)
    fake_client = FakeClient(state.base_url, state.verify_tls)
    monkeypatch.setattr("qrm.query_commands.QrmClient", lambda *a, **kw: fake_client)

    result = runner.invoke(
        _test_app,
        [
            "--config-path",
            str(config_path),
            "--output",
            "json",
        ],
    )
    assert result.exit_code == 0
    out = json.loads(result.stdout)
    assert out["result"] == "ok"
    assert fake_client.called["token"] == "TOKEN123"
    assert "tResultSet" in fake_client.called["query"]
    assert fake_client.called["format"] == "json"
    assert "start" in fake_client.called["parameters"]
    assert "stop" in fake_client.called["parameters"]


def test_query_handles_client_error(monkeypatch, tmp_path):
    state, config_path = make_fake_state(tmp_path)

    class ErrorClient(FakeClient):
        def export_sql(self, *a, **kw):
            raise QrmClientError("fail")

    monkeypatch.setattr(
        "qrm.query_commands.QrmClient",
        lambda *a, **kw: ErrorClient(state.base_url, state.verify_tls),
    )
    result = runner.invoke(
        _test_app,
        ["--config-path", str(config_path)],
    )
    assert result.exit_code == 1
    assert "query failed" in result.stdout


def test_query_invalid_start_stop(monkeypatch, tmp_path):
    state, config_path = make_fake_state(tmp_path)
    fake_client = FakeClient(state.base_url, state.verify_tls)
    monkeypatch.setattr("qrm.query_commands.QrmClient", lambda *a, **kw: fake_client)
    # Invalid ISO format
    result = runner.invoke(
        _test_app,
        ["--config-path", str(config_path), "--start", "not-a-date"],
    )
    assert result.exit_code != 0
    assert "Invalid date format" in result.stdout
