"""
Coverage tests for fee_model.py - untested branches.
"""

import pytest

from bsv.fee_model import FeeModel
from bsv.fee_models.satoshis_per_kilobyte import SatoshisPerKilobyte
from bsv.script.script import Script
from bsv.transaction import Transaction
from bsv.transaction_input import TransactionInput
from bsv.transaction_output import TransactionOutput


def create_mock_transaction(target_size: int) -> Transaction:
    """Create a mock transaction with approximately the target size in bytes."""
    tx = Transaction()

    # Add a simple output (P2PKH output is ~34 bytes)
    output_script = Script(
        b"\x76\xa9\x14" + b"\x00" * 20 + b"\x88\xac"
    )  # OP_DUP OP_HASH160 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG
    tx.add_output(TransactionOutput(output_script, 1000))

    # Calculate remaining size needed and add inputs with appropriate unlocking scripts
    # Base transaction overhead: 4 (version) + 1 (input count varint) + 1 (output count varint) + 4 (locktime) = 10 bytes
    # Output size: 8 (satoshis) + 1 (script length varint) + ~25 (script) = ~34 bytes
    # Input base size: 32 (txid) + 4 (vout) + 1 (script length varint) + 4 (sequence) = 41 bytes

    if target_size <= 50:
        # Minimal transaction - just add empty input
        tx_input = TransactionInput(source_txid="00" * 32, source_output_index=0)
        tx_input.unlocking_script = Script(b"")
        tx.add_input(tx_input)
    else:
        # Add input with script sized to reach target
        script_size = max(1, target_size - 80)  # Approximate remaining size for script
        tx_input = TransactionInput(source_txid="00" * 32, source_output_index=0)
        tx_input.unlocking_script = Script(b"\x00" * script_size)
        tx.add_input(tx_input)

    return tx


# ========================================================================
# SatoshisPerKilobyte branches
# ========================================================================


def test_satoshis_per_kb_init_default():
    """Test SatoshisPerKilobyte with default rate."""
    fee_model = SatoshisPerKilobyte(value=50)
    assert fee_model  # Verify object creation succeeds


def test_satoshis_per_kb_init_custom_rate():
    """Test SatoshisPerKilobyte with custom rate."""
    fee_model = SatoshisPerKilobyte(value=100)
    assert fee_model.value == 100


def test_satoshis_per_kb_init_zero_rate():
    """Test SatoshisPerKilobyte with zero rate."""
    fee_model = SatoshisPerKilobyte(value=0)
    assert fee_model.value == 0


def test_satoshis_per_kb_init_negative_rate():
    """Test SatoshisPerKilobyte with negative rate."""
    try:
        SatoshisPerKilobyte(value=-1)
        # Fee model value is -1 or exception raised
    except ValueError:
        # May validate rate
        pass


def test_satoshis_per_kb_compute_fee_empty():
    """Test compute fee for minimal transaction."""
    fee_model = SatoshisPerKilobyte(value=50)
    tx = create_mock_transaction(target_size=50)
    fee = fee_model.compute_fee(tx)
    assert fee >= 0


def test_satoshis_per_kb_compute_fee_small():
    """Test compute fee for small transaction."""
    fee_model = SatoshisPerKilobyte(value=50)
    tx = create_mock_transaction(target_size=250)  # 1/4 KB
    fee = fee_model.compute_fee(tx)
    assert fee >= 0


def test_satoshis_per_kb_compute_fee_exact_kb():
    """Test compute fee for approximately 1 KB."""
    fee_model = SatoshisPerKilobyte(value=50)
    tx = create_mock_transaction(target_size=1000)
    fee = fee_model.compute_fee(tx)
    assert fee >= 40  # Should be around 50 but allow some variance


def test_satoshis_per_kb_compute_fee_large():
    """Test compute fee for large transaction."""
    fee_model = SatoshisPerKilobyte(value=50)
    tx = create_mock_transaction(target_size=10000)  # 10 KB
    fee = fee_model.compute_fee(tx)
    assert fee >= 400  # Should be around 500 but allow some variance


def test_satoshis_per_kb_compute_fee_fractional():
    """Test compute fee rounds up for fractional KB."""
    fee_model = SatoshisPerKilobyte(value=50)
    tx = create_mock_transaction(target_size=1001)  # Just over 1 KB
    fee = fee_model.compute_fee(tx)
    assert fee >= 50


# ========================================================================
# Edge cases
# ========================================================================


def test_satoshis_per_kb_with_high_rate():
    """Test with very high rate."""
    fee_model = SatoshisPerKilobyte(value=1000000)
    tx = create_mock_transaction(target_size=1000)
    fee = fee_model.compute_fee(tx)
    assert fee >= 900000  # Should be around 1000000 but allow some variance


def test_satoshis_per_kb_compute_fee_boundary():
    """Test compute fee at KB boundary."""
    fee_model = SatoshisPerKilobyte(value=50)
    tx999 = create_mock_transaction(target_size=999)
    tx1000 = create_mock_transaction(target_size=1000)
    tx1001 = create_mock_transaction(target_size=1001)
    fee999 = fee_model.compute_fee(tx999)
    fee1000 = fee_model.compute_fee(tx1000)
    fee1001 = fee_model.compute_fee(tx1001)
    # Fees should generally increase with size
    assert fee999 >= 0 and fee1000 >= 0 and fee1001 >= 0
