"""Template resource tests."""
import httpx
import pytest
from nanorix import ConflictError, PayloadTooLargeError

TEST_API_KEY = "nrx_test_sk_test_1234567890abcdef"
TEST_BASE_URL = "https://api.nanorix.io"

TEMPLATE_RESPONSE = {
    "id": "tmpl_abc12345",
    "name": "test-model",
    "runtime": "python3.11",
    "entrypoint": "python model.py",
    "status": "ready",
    "version": 1,
    "total_size_bytes": 1024,
    "content_hash": "abc123",
    "created_at": "2026-03-25T00:00:00Z",
    "files": [
        {"id": "tf_001", "filename": "model.py", "size_bytes": 512, "sha256": "sha_a"},
        {"id": "tf_002", "filename": "requirements.txt", "size_bytes": 512, "sha256": "sha_b"},
    ],
}


def test_create_template_three_step(mock_api, client):
    """Mock all 3 API calls and verify order."""
    mock_api.post("/v1/templates").mock(
        return_value=httpx.Response(200, json={"id": "tmpl_abc12345"})
    )
    mock_api.post("/v1/templates/tmpl_abc12345/files").mock(
        return_value=httpx.Response(200, json={"filename": "model.py", "size_bytes": 100, "sha256": "abc"})
    )
    mock_api.post("/v1/templates/tmpl_abc12345/finalize").mock(
        return_value=httpx.Response(200, json=TEMPLATE_RESPONSE)
    )

    tmpl = client.templates.create(
        name="test-model",
        runtime="python3.11",
        entrypoint="python model.py",
        files={"model.py": b"print('hello')"},
    )

    assert tmpl.id == "tmpl_abc12345"
    assert tmpl.name == "test-model"
    assert tmpl.status == "ready"


def test_create_template_with_file_paths(mock_api, client, tmp_path):
    """Verify file reading from disk."""
    model_file = tmp_path / "model.py"
    model_file.write_text("print('test')")

    mock_api.post("/v1/templates").mock(
        return_value=httpx.Response(200, json={"id": "tmpl_xyz"})
    )
    mock_api.post("/v1/templates/tmpl_xyz/files").mock(
        return_value=httpx.Response(200, json={"filename": "model.py", "size_bytes": 14, "sha256": "x"})
    )
    mock_api.post("/v1/templates/tmpl_xyz/finalize").mock(
        return_value=httpx.Response(200, json={**TEMPLATE_RESPONSE, "id": "tmpl_xyz"})
    )

    tmpl = client.templates.create(
        name="test",
        runtime="python3.11",
        entrypoint="python model.py",
        files=[str(model_file)],
    )
    assert tmpl.id == "tmpl_xyz"


def test_create_template_with_bytes_dict(mock_api, client):
    """Verify bytes upload."""
    mock_api.post("/v1/templates").mock(
        return_value=httpx.Response(200, json={"id": "tmpl_bytes"})
    )
    mock_api.post("/v1/templates/tmpl_bytes/files").mock(
        return_value=httpx.Response(200, json={"filename": "x", "size_bytes": 5, "sha256": "y"})
    )
    mock_api.post("/v1/templates/tmpl_bytes/finalize").mock(
        return_value=httpx.Response(200, json={**TEMPLATE_RESPONSE, "id": "tmpl_bytes"})
    )

    tmpl = client.templates.create(
        name="test",
        runtime="python3.11",
        entrypoint="python model.py",
        files={"model.py": b"hello", "req.txt": b"numpy"},
    )
    assert tmpl.id == "tmpl_bytes"


def test_list_templates(mock_api, client):
    mock_api.get("/v1/templates").mock(
        return_value=httpx.Response(200, json={
            "templates": [TEMPLATE_RESPONSE],
            "has_more": False,
        })
    )

    result = client.templates.list()
    assert len(result.templates) == 1
    assert result.templates[0].id == "tmpl_abc12345"
    assert not result.has_more


def test_get_template(mock_api, client):
    mock_api.get("/v1/templates/tmpl_abc12345").mock(
        return_value=httpx.Response(200, json=TEMPLATE_RESPONSE)
    )

    tmpl = client.templates.get("tmpl_abc12345")
    assert tmpl.id == "tmpl_abc12345"
    assert tmpl.runtime == "python3.11"
    assert len(tmpl.files) == 2


def test_delete_template(mock_api, client):
    mock_api.delete("/v1/templates/tmpl_abc12345").mock(
        return_value=httpx.Response(204)
    )

    result = client.templates.delete("tmpl_abc12345")
    assert result is None


def test_wait_until_ready_succeeds(mock_api, client):
    """Mock GET returning 'building' then 'ready'."""
    responses = [
        httpx.Response(200, json={**TEMPLATE_RESPONSE, "status": "building"}),
        httpx.Response(200, json={**TEMPLATE_RESPONSE, "status": "ready"}),
    ]
    mock_api.get("/v1/templates/tmpl_abc12345").mock(side_effect=responses)

    tmpl = client.templates.wait_until_ready("tmpl_abc12345", poll_interval=0.01)
    assert tmpl.status == "ready"


def test_create_template_duplicate_name_conflict(mock_api, client):
    mock_api.post("/v1/templates").mock(
        return_value=httpx.Response(409, json={"error": "Template name already exists"})
    )

    with pytest.raises(ConflictError, match="already exists"):
        client.templates.create(
            name="duplicate",
            runtime="python3.11",
            entrypoint="python x.py",
            files={"x.py": b"pass"},
        )


def test_create_template_exceeds_size_limit(mock_api, client):
    mock_api.post("/v1/templates").mock(
        return_value=httpx.Response(200, json={"id": "tmpl_big"})
    )
    mock_api.post("/v1/templates/tmpl_big/files").mock(
        return_value=httpx.Response(413, json={"error": "File exceeds tier limit"})
    )

    with pytest.raises(PayloadTooLargeError, match="tier limit"):
        client.templates.create(
            name="big",
            runtime="python3.11",
            entrypoint="python x.py",
            files={"huge.bin": b"x" * 100},
        )
