from datetime import datetime, timezone, timedelta

# Import necessary classes from models.py
from src.models import Metadata, TrackState, Ticket

# --- Pytest Tests ---

def test_track_state_instantiation() -> None:
 """Test creating a TrackState object."""
 now = datetime.now(timezone.utc)
 metadata = Metadata(
  id="track-123",
  name="Initial Setup",
  status="in_progress",
  created_at=now - timedelta(days=1),
  updated_at=now,
 )
 discussion = [
  {"role": "user", "content": "Hello", "ts": now - timedelta(hours=1)},
  {"role": "assistant", "content": "Hi there!", "ts": now - timedelta(hours=2)},
 ]
 # Update Ticket instantiation to match models.py fields (description, assigned_to)
 tasks = [
  Ticket(id="task-a", description="Design UI", status="todo", assigned_to="dev1"),
  Ticket(id="task-b", description="Implement Backend", status="todo", assigned_to="dev2"),
 ]
 track_state = TrackState(
  metadata=metadata,
  discussion=discussion,
  tasks=tasks,
 )
 assert track_state.metadata.id == "track-123"
 assert len(track_state.discussion) == 2
 assert len(track_state.tasks) == 2
 assert isinstance(track_state.tasks[0], Ticket)
 assert track_state.tasks[0].description == "Design UI"
 assert track_state.tasks[0].assigned_to == "dev1"

def test_track_state_to_dict() -> None:
 """Test the to_dict() method for serialization."""
 now = datetime.now(timezone.utc)
 metadata = Metadata(
  id="track-456",
  name="Refinement Phase",
  status="completed",
  created_at=now - timedelta(days=5),
  updated_at=now - timedelta(days=2),
 )
 discussion = [
  {"role": "user", "content": "Need changes", "ts": now - timedelta(hours=3)},
  {"role": "assistant", "content": "Understood.", "ts": now - timedelta(hours=4)},
 ]
 # Update Ticket instantiation
 tasks = [
  Ticket(id="task-c", description="Add feature X", status="in_progress", assigned_to="dev3"),
 ]
 track_state = TrackState(
  metadata=metadata,
  discussion=discussion,
  tasks=tasks,
 )
 track_dict = track_state.to_dict()
 assert track_dict["metadata"]["id"] == "track-456"
 assert track_dict["metadata"]["created_at"] == metadata.created_at.isoformat()
 assert track_dict["metadata"]["updated_at"] == metadata.updated_at.isoformat()
 assert len(track_dict["discussion"]) == 2
 assert track_dict["discussion"][0]["ts"] == discussion[0]["ts"].isoformat()
 assert len(track_dict["tasks"]) == 1
 # Use the Ticket's to_dict method for serialization
 assert track_dict["tasks"][0]["id"] == "task-c"
 assert track_dict["tasks"][0]["description"] == "Add feature X"
 assert track_dict["tasks"][0]["assigned_to"] == "dev3"

def test_track_state_from_dict() -> None:
 """Test the from_dict() class method for deserialization."""
 now = datetime.now(timezone.utc)
 track_dict_data = {
  "metadata": {
   "id": "track-789",
   "name": "Final Review",
   "status": "pending",
   "created_at": (now - timedelta(days=10)).isoformat(),
   "updated_at": (now - timedelta(days=9)).isoformat(),
  },
  "discussion": [
   {"role": "user", "content": "Review complete.", "ts": (now - timedelta(hours=5)).isoformat()},
  ],
  "tasks": [
   # Use fields from models.py Ticket definition for deserialization
   {"id": "task-d", "description": "Deploy", "status": "completed", "assigned_to": "ops1"},
  ],
 }
 track_state = TrackState.from_dict(track_dict_data)
 assert isinstance(track_state, TrackState)
 assert track_state.metadata.id == "track-789"
 assert isinstance(track_state.metadata.created_at, datetime)
 assert track_state.metadata.created_at.isoformat() == track_dict_data["metadata"]["created_at"]
 assert len(track_state.discussion) == 1
 assert isinstance(track_state.discussion[0]["ts"], datetime)
 assert track_state.discussion[0]["ts"].isoformat() == track_dict_data["discussion"][0]["ts"]
 assert len(track_state.tasks) == 1
 assert isinstance(track_state.tasks[0], Ticket)
 assert track_state.tasks[0].id == "task-d"
 assert track_state.tasks[0].description == "Deploy"
 assert track_state.tasks[0].assigned_to == "ops1"
 # Test case for empty lists and missing keys for robustness

def test_track_state_from_dict_empty_and_missing() -> None:
 """Test from_dict with empty lists and missing optional keys."""
 track_dict_data = {
  "metadata": {
   "id": "track-empty",
   "name": "Empty State",
   # created_at, updated_at, status are optional in from_dict logic
  },
  "discussion": [], # Empty discussion list
  "tasks": [], # Empty tasks list
 }
 track_state = TrackState.from_dict(track_dict_data)
 assert isinstance(track_state, TrackState)
 assert track_state.metadata.id == "track-empty"
 assert track_state.metadata.name == "Empty State"
 assert track_state.metadata.created_at is None
 assert track_state.metadata.updated_at is None
 assert track_state.metadata.status is None
 assert len(track_state.discussion) == 0
 assert len(track_state.tasks) == 0
 # Test case for to_dict with None values or missing optional data

def test_track_state_to_dict_with_none() -> None:
 """Test to_dict with None values in optional fields."""
 now = datetime.now(timezone.utc)
 metadata = Metadata(
  id="track-none",
  name="None Test",
  status=None, # None status
  created_at=now,
  updated_at=None, # None updated_at
 )
 discussion = [
  {"role": "system", "content": "Info", "ts": None}, # None timestamp
 ]
 # Update Ticket instantiation
 tasks = [
  Ticket(id="task-none", description="Task None", status="pending", assigned_to="anon"),
 ]
 track_state = TrackState(
  metadata=metadata,
  discussion=discussion,
  tasks=tasks,
 )
 track_dict = track_state.to_dict()
 assert track_dict["metadata"]["status"] is None
 # Check that isoformat was called on datetime object, not None
 assert track_dict["metadata"]["created_at"] == now.isoformat()
 assert track_dict["metadata"]["updated_at"] is None # This should be None as it's passed as None
 assert track_dict["discussion"][0]["ts"] is None
 assert track_dict["tasks"][0]["description"] == "Task None"
 assert track_dict["tasks"][0]["assigned_to"] == "anon"