import pytest
import time
from src.history import HistoryManager, HistoryEntry

def test_initial_state():
 hm = HistoryManager(max_capacity=5)
 assert hm.can_undo is False
 assert hm.can_redo is False
 assert hm.get_history() == []

def test_push_state():
 hm = HistoryManager(max_capacity=5)
 hm.push("state1", "action1")
 assert hm.can_undo is True
 assert hm.can_redo is False
 history = hm.get_history()
 assert len(history) == 1
 assert history[0]["description"] == "action1"

def test_undo_redo():
 hm = HistoryManager(max_capacity=5)
 s0 = "S0"
 s1 = "S1"
 s2 = "S2"
 
 # Start at S0, change to S1
 hm.push(s0, "Initial")
 # Now at S1, change to S2
 hm.push(s1, "Action 1")
 # Now at S2
 
 # Undo Action 1 (go back to S1)
 entry = hm.undo(s2, "Current at S2")
 assert entry.state == s1
 assert entry.description == "Action 1"
 assert hm.can_undo is True
 assert hm.can_redo is True
 
 # Undo Initial (go back to S0)
 entry = hm.undo(s1, "Current at S1")
 assert entry.state == s0
 assert entry.description == "Initial"
 assert hm.can_undo is False
 assert hm.can_redo is True
 
 # Redo Initial (go back to S1)
 entry = hm.redo(s0, "Back at S0")
 assert entry.state == s1
 assert entry.description == "Current at S1"
 assert hm.can_undo is True
 assert hm.can_redo is True
 
 # Redo Action 1 (go back to S2)
 entry = hm.redo(s1, "Back at S1")
 assert entry.state == s2
 assert entry.description == "Current at S2"
 assert hm.can_undo is True
 assert hm.can_redo is False

def test_max_capacity():
 hm = HistoryManager(max_capacity=2)
 hm.push("S0", "D0")
 hm.push("S1", "D1")
 hm.push("S2", "D2")
 assert len(hm._undo_stack) == 2
 assert hm._undo_stack[0].description == "D1"
 assert hm._undo_stack[1].description == "D2"

def test_redo_cleared_on_push():
 hm = HistoryManager(max_capacity=5)
 hm.push("S0", "D0")
 hm.undo("S1", "D1")
 assert hm.can_redo is True
 hm.push("S2", "D2")
 assert hm.can_redo is False

def test_jump_to_undo():
 hm = HistoryManager(max_capacity=10)
 hm.push("S0", "D0")
 hm.push("S1", "D1")
 hm.push("S2", "D2")
 hm.push("S3", "D3")
 
 # Current state is S4
 # Jump to S1 (index 1)
 entry = hm.jump_to_undo(1, "S4", "Before Jump")
 assert entry.state == "S1"
 assert hm.can_undo is True # S0 is still there
 assert len(hm._undo_stack) == 1
 assert hm.can_redo is True
 # Redo stack should have [S4, S3, S2]
 assert len(hm._redo_stack) == 3
 assert hm._redo_stack[-1].state == "S2"
