"""Tests for signed invite-code licensing and activation ledger."""

from __future__ import annotations

import json
from pathlib import Path

import pytest

from model_osmosis.services.invite_licensing import (
    activate_invite_code,
    create_invite_code,
    license_status,
    load_activation_ledger,
    verify_invite_code,
)


@pytest.fixture(autouse=True)
def _trust_home_tmp(monkeypatch, tmp_path):
    monkeypatch.setenv("OSMOSIS_TRUST_HOME", str(tmp_path / "trust"))
    monkeypatch.setenv("OSMOSIS_INVITE_ISSUER", "1")


def test_invite_roundtrip_create_verify_activate_status():
    created = create_invite_code(
        signer_id="default",
        subject="test-user",
        max_activations=1,
        valid_days=7,
    )
    code = str(created["invite_code"])

    verify = verify_invite_code(code)
    assert verify["status"] == "valid"
    assert verify["trust_status"] in {"trusted", "signed_untrusted"}
    assert verify["remaining_activations"] == 1

    activated = activate_invite_code(code)
    assert activated["status"] == "activated"
    assert activated["remaining_activations"] == 0

    activated_again = activate_invite_code(code)
    assert activated_again["status"] == "already_active"

    status = license_status()
    assert status["status"] == "active"
    assert status["verify"]["status"] == "valid"


def test_activation_limit_enforced_for_different_machine():
    created = create_invite_code(max_activations=1, valid_days=3)
    code = str(created["invite_code"])

    first = activate_invite_code(code, machine_id="machine-a")
    assert first["status"] == "activated"

    with pytest.raises(RuntimeError, match="activation limit reached"):
        activate_invite_code(code, machine_id="machine-b")


def test_verify_expired_invite_code():
    created = create_invite_code(expires_at="2001-01-01T00:00:00Z", max_activations=1)
    verify = verify_invite_code(str(created["invite_code"]))
    assert verify["status"] == "expired"
    assert verify["is_expired"] is True


def test_ledger_tamper_detection():
    created = create_invite_code(max_activations=2, valid_days=5)
    activate_invite_code(str(created["invite_code"]), machine_id="machine-a")

    ledger = load_activation_ledger()
    assert ledger["valid"] is True
    path = Path(str(ledger["path"]))
    lines = path.read_text(encoding="utf-8").splitlines()
    assert lines
    first = json.loads(lines[0])
    first["machine_id"] = "tampered"
    lines[0] = json.dumps(first, sort_keys=True, separators=(",", ":"))
    path.write_text("\n".join(lines) + "\n", encoding="utf-8")

    tampered = load_activation_ledger()
    assert tampered["valid"] is False
    assert "mismatch" in str(tampered["reason"])


def test_invite_create_requires_issuer_mode(monkeypatch):
    monkeypatch.setenv("OSMOSIS_INVITE_ISSUER", "0")
    with pytest.raises(PermissionError, match="restricted to issuer mode"):
        create_invite_code(max_activations=1, valid_days=3)
