import pytest
from unittest.mock import patch
from src.models import Ticket

def test_ticket_priority_default():
 ticket = Ticket(id="T1", description="Test ticket")
 assert ticket.priority == "medium"

def test_ticket_priority_custom():
 ticket_high = Ticket(id="T2", description="High priority", priority="high")
 assert ticket_high.priority == "high"
 
 ticket_low = Ticket(id="T3", description="Low priority", priority="low")
 assert ticket_low.priority == "low"

def test_ticket_to_dict_priority():
 ticket = Ticket(id="T4", description="To dict test", priority="high")
 d = ticket.to_dict()
 assert "priority" in d
 assert d["priority"] == "high"

def test_ticket_from_dict_priority():
 data = {
  "id": "T5",
  "description": "From dict test",
  "priority": "low",
  "status": "todo"
 }
 ticket = Ticket.from_dict(data)
 assert ticket.priority == "low"

def test_ticket_from_dict_default_priority():
 data = {
  "id": "T6",
  "description": "No priority in dict"
 }
 ticket = Ticket.from_dict(data)
 assert ticket.priority == "medium"

class TestBulkOperations:
 def test_bulk_execute(self, mock_app):
  mock_app.active_tickets = [
   {"id": "T1", "status": "todo"},
   {"id": "T2", "status": "todo"},
   {"id": "T3", "status": "todo"}
  ]
  mock_app.ui_selected_tickets = {"T1", "T3"}
  
  with patch.object(mock_app.controller, "_push_mma_state_update") as mock_push:
   mock_app.bulk_execute()
   assert mock_app.active_tickets[0]["status"] == "in_progress"
   assert mock_app.active_tickets[1]["status"] == "todo"
   assert mock_app.active_tickets[2]["status"] == "in_progress"
   mock_push.assert_called_once()

 def test_bulk_skip(self, mock_app):
  mock_app.active_tickets = [
   {"id": "T1", "status": "todo"},
   {"id": "T2", "status": "todo"}
  ]
  mock_app.ui_selected_tickets = {"T1"}
  
  with patch.object(mock_app.controller, "_push_mma_state_update") as mock_push:
   mock_app.bulk_skip()
   assert mock_app.active_tickets[0]["status"] == "completed"
   assert mock_app.active_tickets[1]["status"] == "todo"
   mock_push.assert_called_once()

 def test_bulk_block(self, mock_app):
  mock_app.active_tickets = [
   {"id": "T1", "status": "todo"},
   {"id": "T2", "status": "todo"}
  ]
  mock_app.ui_selected_tickets = {"T1", "T2"}
  
  with patch.object(mock_app.controller, "_push_mma_state_update") as mock_push:
   mock_app.bulk_block()
   assert mock_app.active_tickets[0]["status"] == "blocked"
   assert mock_app.active_tickets[1]["status"] == "blocked"
   mock_push.assert_called_once()

class TestReorder:
 def test_reorder_ticket_valid(self, mock_app):
  mock_app.active_tickets = [
   {"id": "T1", "depends_on": []},
   {"id": "T2", "depends_on": []},
   {"id": "T3", "depends_on": ["T1"]}
  ]
  with patch.object(mock_app.controller, "_push_mma_state_update") as mock_push:
   # Move T1 to index 1: [T2, T1, T3]. T3 depends on T1. T1 index 1 < T3 index 2. VALID.
   mock_app._reorder_ticket(0, 1)
   assert mock_app.active_tickets[0]["id"] == "T2"
   assert mock_app.active_tickets[1]["id"] == "T1"
   assert mock_app.active_tickets[2]["id"] == "T3"
   mock_push.assert_called_once()

 def test_reorder_ticket_invalid(self, mock_app):
  mock_app.active_tickets = [
   {"id": "T1", "depends_on": []},
   {"id": "T2", "depends_on": ["T1"]}
  ]
  with patch.object(mock_app.controller, "_push_mma_state_update") as mock_push:
   # Move T1 after T2: [T2, T1]. T2 depends on T1, but T1 is now at index 1 while T2 is at index 0.
   # Violation: dependency T1 (index 1) is not before T2 (index 0).
   mock_app._reorder_ticket(0, 1)
   # Should NOT change
   assert mock_app.active_tickets[0]["id"] == "T1"
   assert mock_app.active_tickets[1]["id"] == "T2"
   mock_push.assert_not_called()
