"""Unit tests for the lightning package (factory + ledger)."""

from __future__ import annotations

import pytest

from lightning.factory import Invoice, MockBackend, get_backend
from lightning.ledger import (
    TxStatus,
    TxType,
    clear,
    create_invoice_entry,
    get_balance,
    get_transactions,
    mark_settled,
)


@pytest.fixture(autouse=True)
def _clean_ledger():
    """Reset the in-memory ledger between tests."""
    clear()
    yield
    clear()


# ── Factory tests ────────────────────────────────────────────────────


class TestMockBackend:
    def test_create_invoice_returns_invoice(self):
        backend = MockBackend()
        inv = backend.create_invoice(100, "test memo")
        assert isinstance(inv, Invoice)
        assert inv.amount_sats == 100
        assert inv.memo == "test memo"
        assert len(inv.payment_hash) == 64  # SHA-256 hex
        assert inv.payment_request.startswith("lnbc")

    def test_invoices_have_unique_hashes(self):
        backend = MockBackend()
        a = backend.create_invoice(10)
        b = backend.create_invoice(10)
        assert a.payment_hash != b.payment_hash


class TestGetBackend:
    def test_returns_mock_backend(self):
        backend = get_backend()
        assert isinstance(backend, MockBackend)


# ── Ledger tests ─────────────────────────────────────────────────────


class TestLedger:
    def test_create_invoice_entry(self):
        entry = create_invoice_entry(
            payment_hash="abc123",
            amount_sats=500,
            memo="test",
            source="unit_test",
        )
        assert entry.tx_type == TxType.incoming
        assert entry.status == TxStatus.pending
        assert entry.amount_sats == 500

    def test_mark_settled(self):
        create_invoice_entry(payment_hash="hash1", amount_sats=100)
        result = mark_settled("hash1", preimage="secret")
        assert result is not None
        assert result.status == TxStatus.settled
        assert result.preimage == "secret"
        assert result.settled_at != ""

    def test_mark_settled_unknown_hash(self):
        assert mark_settled("nonexistent") is None

    def test_get_balance_empty(self):
        bal = get_balance()
        assert bal["net_sats"] == 0
        assert bal["available_sats"] == 0

    def test_get_balance_with_settled(self):
        create_invoice_entry(payment_hash="h1", amount_sats=1000)
        mark_settled("h1")
        bal = get_balance()
        assert bal["incoming_total_sats"] == 1000
        assert bal["net_sats"] == 1000
        assert bal["available_sats"] == 1000

    def test_get_balance_pending_not_counted(self):
        create_invoice_entry(payment_hash="h2", amount_sats=500)
        bal = get_balance()
        assert bal["incoming_total_sats"] == 0
        assert bal["pending_incoming_sats"] == 500

    def test_get_transactions_returns_entries(self):
        create_invoice_entry(payment_hash="t1", amount_sats=10)
        create_invoice_entry(payment_hash="t2", amount_sats=20)
        txs = get_transactions()
        assert len(txs) == 2

    def test_get_transactions_filter_by_status(self):
        create_invoice_entry(payment_hash="f1", amount_sats=10)
        create_invoice_entry(payment_hash="f2", amount_sats=20)
        mark_settled("f1")
        assert len(get_transactions(status="settled")) == 1
        assert len(get_transactions(status="pending")) == 1
