from __future__ import annotations
from unittest.mock import patch, MagicMock

from src import gui_2
from src.gui_2 import App


def _make_app(**kwargs):
 """
  [C: tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier1_renders_stream_content, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders]
 """
 app = MagicMock()
 app.mma_streams = kwargs.get("mma_streams", {})
 app.mma_tier_usage = kwargs.get("mma_tier_usage", {
  "Tier 1": {"input": 0, "output": 0, "model": "gemini-3.1-pro-preview"},
  "Tier 2": {"input": 0, "output": 0, "model": "gemini-3-flash-preview"},
  "Tier 3": {"input": 0, "output": 0, "model": "gemini-2.5-flash-lite"},
  "Tier 4": {"input": 0, "output": 0, "model": "gemini-2.5-flash-lite"},
 })
 app.ui_focus_agent = kwargs.get("ui_focus_agent", None)
 app.tracks = kwargs.get("tracks", [])
 app.active_track = kwargs.get("active_track", None)
 app.active_tickets = kwargs.get("active_tickets", [])
 app.mma_status = kwargs.get("mma_status", "idle")
 app.active_tier = kwargs.get("active_tier", None)
 app.mma_step_mode = kwargs.get("mma_step_mode", False)
 app._pending_mma_spawns = []
 app._pending_mma_approvals = []
 spawn = kwargs.get("_pending_mma_spawn", None)
 app._pending_mma_spawn = spawn
 if spawn:
  app._pending_mma_spawns.append(spawn)
 approval = kwargs.get("_pending_mma_approval", None)
 app._pending_mma_approval = approval
 if approval:
  app._pending_mma_approvals.append(approval)
 app._pending_ask_dialog = kwargs.get("_pending_ask_dialog", False)
 app.perf_profiling_enabled = False
 app.ui_new_track_name = ""
 app.ui_new_track_desc = ""
 app.ui_new_track_type = "feature"
 app.ui_conductor_setup_summary = ""
 app.ui_epic_input = ""
 app._show_add_ticket_form = False
 app.ui_new_ticket_id = ""
 app.ui_new_ticket_desc = ""
 app.ui_new_ticket_target = ""
 app.ui_new_ticket_deps = ""
 app.ui_selected_ticket_id = ""
 app.is_viewing_prior_session = False
 app.ui_separate_task_dag = False
 app.ui_separate_tier1 = False
 app.ui_separate_tier2 = False
 app.ui_separate_tier3 = False
 app.ui_separate_tier4 = False
 app.show_windows = {}
 app.proposed_tracks = []
 app._avg_ticket_time = 300
 mock_engine = MagicMock()
 mock_engine._pause_event = MagicMock()
 mock_engine._pause_event.is_set.return_value = False
 mock_controller = MagicMock()
 mock_controller.engine = mock_engine
 app.controller = mock_controller
 
 # Ensure real methods are called for the dashboard rendering components
 app._render_mma_dashboard = lambda: gui_2.render_mma_dashboard(app)
 app._render_mma_focus_selector = lambda: gui_2.render_mma_focus_selector(app)
 app._render_mma_track_summary = lambda: gui_2.render_mma_track_summary(app)
 app._render_mma_epic_planner = lambda: gui_2.render_mma_epic_planner(app)
 app._render_mma_conductor_setup = lambda: gui_2.render_mma_conductor_setup(app)
 app._render_mma_track_browser = lambda: gui_2.render_mma_track_browser(app)
 app._render_mma_global_controls = lambda: gui_2.render_mma_global_controls(app)
 app._render_mma_usage_section = lambda: gui_2.render_mma_usage_section(app)
 app._render_ticket_queue = lambda: gui_2.render_ticket_queue(app)
 app._render_window_if_open = lambda name, func, condition=True: func() if condition else None
 app._render_mma_ticket_editor = lambda: gui_2.render_mma_ticket_editor(app)
 app._render_mma_agent_streams = lambda: gui_2.render_mma_agent_streams(app)

 return app

def _make_imgui_mock():
 """
  [C: tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier1_renders_stream_content, tests/test_mma_dashboard_streams.py:TestMMADashboardStreams.test_tier3_renders_worker_subheaders]
 """
 m = MagicMock()
 m.begin_table.return_value = False
 m.begin_child.return_value = False
 m.checkbox.return_value = (False, False)
 m.button.return_value = False
 m.input_text.side_effect = lambda label, value, *args, **kwargs: (False, value)
 m.input_text_multiline.side_effect = lambda label, value, *args, **kwargs: (False, value)
 m.combo.side_effect = lambda label, current_item, items, *args, **kwargs: (False, current_item)
 m.collapsing_header.return_value = False
 m.begin_combo.return_value = False
 m.ImVec2.return_value = MagicMock()
 m.ImVec4.return_value = MagicMock()
 return m

def _collect_text_colored_args(imgui_mock):
 """Return a single joined string of all text_colored second-arg strings."""
 parts = []
 for c in imgui_mock.text_colored.call_args_list:
  args = c.args
  if len(args) >= 2:
   parts.append(str(args[1]))
 return " ".join(parts)


class TestMMAApprovalIndicators:

 def test_no_approval_badge_when_idle(self):
  """No 'APPROVAL PENDING' badge when all pending attrs are None/False."""
  app = _make_app(
   _pending_mma_spawn=None,
   _pending_mma_approval=None,
   _pending_ask_dialog=False,
  )
  imgui_mock = _make_imgui_mock()
  with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.imscope") as mock_imscope:
   # Setup imscope mocks
   mock_imscope.window.return_value.__enter__.return_value = (True, True)
   mock_imscope.child.return_value.__enter__.return_value = True
   mock_imscope.table.return_value.__enter__.return_value = True
   mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
   mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
   mock_imscope.style_color.return_value.__enter__.return_value = None
   mock_imscope.style_var.return_value.__enter__.return_value = None

   gui_2.render_mma_dashboard(app)
  combined = _collect_text_colored_args(imgui_mock)
  assert "APPROVAL PENDING" not in combined, (
   "text_colored called with 'APPROVAL PENDING' when no approval is pending"
  )

 def test_approval_badge_shown_when_spawn_pending(self):
  """'APPROVAL PENDING' badge must appear when _pending_mma_spawn is set."""
  app = _make_app(_pending_mma_spawn={"ticket_id": "T-001"})
  imgui_mock = _make_imgui_mock()
  with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.imscope") as mock_imscope, patch("src.gui_2.math") as mock_math:
   # Setup imscope mocks
   mock_imscope.window.return_value.__enter__.return_value = (True, True)
   mock_imscope.child.return_value.__enter__.return_value = True
   mock_imscope.table.return_value.__enter__.return_value = True
   mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
   mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
   mock_imscope.style_color.return_value.__enter__.return_value = None
   mock_imscope.style_var.return_value.__enter__.return_value = None

   mock_math.sin.return_value = 0.8
   gui_2.render_mma_dashboard(app)
  combined = _collect_text_colored_args(imgui_mock)
  assert "APPROVAL PENDING" in combined, (
   "text_colored not called with 'APPROVAL PENDING' when _pending_mma_spawn is set"
  )

 def test_approval_badge_shown_when_mma_approval_pending(self):
  """'APPROVAL PENDING' badge must appear when _pending_mma_approval is set."""
  app = _make_app(_pending_mma_approval={"step": "test"})
  imgui_mock = _make_imgui_mock()
  with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.imscope") as mock_imscope, patch("src.gui_2.math") as mock_math:
   # Setup imscope mocks
   mock_imscope.window.return_value.__enter__.return_value = (True, True)
   mock_imscope.child.return_value.__enter__.return_value = True
   mock_imscope.table.return_value.__enter__.return_value = True
   mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
   mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
   mock_imscope.style_color.return_value.__enter__.return_value = None
   mock_imscope.style_var.return_value.__enter__.return_value = None

   mock_math.sin.return_value = 0.8
   gui_2.render_mma_dashboard(app)
  combined = _collect_text_colored_args(imgui_mock)
  assert "APPROVAL PENDING" in combined, (
   "text_colored not called with 'APPROVAL PENDING' when _pending_mma_approval is set"
  )

 def test_approval_badge_shown_when_ask_dialog_pending(self):
  """'APPROVAL PENDING' badge must appear when _pending_ask_dialog is True."""
  app = _make_app(_pending_ask_dialog=True)
  imgui_mock = _make_imgui_mock()
  with patch("src.gui_2.imgui", imgui_mock), patch("src.gui_2.imscope") as mock_imscope, patch("src.gui_2.math") as mock_math:
   # Setup imscope mocks
   mock_imscope.window.return_value.__enter__.return_value = (True, True)
   mock_imscope.child.return_value.__enter__.return_value = True
   mock_imscope.table.return_value.__enter__.return_value = True
   mock_imscope.tree_node_ex.return_value.__enter__.return_value = True
   mock_imscope.tab_item.return_value.__enter__.return_value = (True, True)
   mock_imscope.style_color.return_value.__enter__.return_value = None
   mock_imscope.style_var.return_value.__enter__.return_value = None

   mock_math.sin.return_value = 0.8
   gui_2.render_mma_dashboard(app)
  combined = _collect_text_colored_args(imgui_mock)
  assert "APPROVAL PENDING" in combined, (
   "text_colored not called with 'APPROVAL PENDING' when _pending_ask_dialog is True"
  )