"""Tests for run_mssql_query: composition of mssql_connect + mssql_query.

Mock-based, no real SQL Server. The pipeline binds `mssql_connect` and
`mssql_query` as module-level names, so we monkeypatch them in the pipeline's
namespace and assert the orchestration (connect -> query -> always close).
"""

from __future__ import annotations

import pytest

import pipelines.run_mssql_query as mod
from pipelines.run_mssql_query import run_mssql_query, _to_csv


class FakeConn:
    def __init__(self):
        self.closed = False

    def close(self):
        self.closed = True


def test_run_mssql_query_composes_connect_and_query(monkeypatch):
    fake_conn = FakeConn()
    connect_calls = {}
    query_calls = {}

    def fake_connect(host, database, user, password, **kwargs):
        connect_calls.update(
            host=host, database=database, user=user, password=password, **kwargs
        )
        return fake_conn

    sentinel = {"columns": ["No_"], "rows": [{"No_": "CLI-1"}], "row_count": 1}

    def fake_query(conn, sql, params=None, max_rows=None):
        query_calls.update(conn=conn, sql=sql, params=params, max_rows=max_rows)
        return sentinel

    monkeypatch.setattr(mod, "mssql_connect", fake_connect)
    monkeypatch.setattr(mod, "mssql_query", fake_query)

    result = run_mssql_query(
        "10.0.0.5", "navdb", "sa", "pw",
        "SELECT [No_] FROM [dbo].[Cartera] WHERE [Customer No_] = %s",
        params=("CLI-0001",), port=1433, max_rows=5,
    )

    # Returns exactly what mssql_query produced.
    assert result is sentinel
    # Connection was opened with the supplied params.
    assert connect_calls["host"] == "10.0.0.5"
    assert connect_calls["database"] == "navdb"
    assert connect_calls["port"] == 1433
    # Query borrowed the open connection and got the bound params (no interpolation).
    assert query_calls["conn"] is fake_conn
    assert query_calls["params"] == ("CLI-0001",)
    assert query_calls["max_rows"] == 5
    # Connection is always closed.
    assert fake_conn.closed is True


def test_run_mssql_query_closes_connection_on_error(monkeypatch):
    fake_conn = FakeConn()

    monkeypatch.setattr(mod, "mssql_connect", lambda *a, **k: fake_conn)

    def boom(conn, sql, params=None, max_rows=None):
        raise RuntimeError("mssql_query failed executing query: boom")

    monkeypatch.setattr(mod, "mssql_query", boom)

    with pytest.raises(RuntimeError, match="failed executing query"):
        run_mssql_query("10.0.0.5", "navdb", "sa", "pw", "SELECT 1")

    # Even on a query error, the connection is closed (try/finally).
    assert fake_conn.closed is True


def test_to_csv_renders_header_and_rows():
    result = {
        "columns": ["No_", "Amount"],
        "rows": [
            {"No_": "CLI-1", "Amount": 100},
            {"No_": "CLI-2", "Amount": 200},
        ],
        "row_count": 2,
    }
    csv_text = _to_csv(result)
    lines = csv_text.strip().splitlines()
    assert lines[0] == "No_,Amount"
    assert lines[1] == "CLI-1,100"
    assert lines[2] == "CLI-2,200"
