from types import SimpleNamespace

import pytest

from services.intelligence.agents.core_agent_framework import TaskProposal
from services import today_workflow_service as svc


class DummyActivity:
    def __init__(self, *args, **kwargs):
        pass

    def start_run(self, *args, **kwargs):
        return SimpleNamespace(id="run-1")

    def log_event(self, *args, **kwargs):
        return None

    def finish_run(self, *args, **kwargs):
        return None


class DummyMemoryService:
    def __init__(self, user_id, db):
        pass

    async def filter_redundant_proposals(self, proposals):
        return proposals


class DummyAgent:
    def __init__(self, proposals):
        self._proposals = proposals

    async def propose_daily_tasks(self, grounding):
        return self._proposals


def _mock_orchestrator_with_agents(content_proposals=None, strategy_proposals=None):
    return SimpleNamespace(
        agents={
            "content": DummyAgent(content_proposals or []),
            "strategy": DummyAgent(strategy_proposals or []),
            "seo": None,
            "social": None,
            "competitor": None,
        }
    )


def _covered_pillars(result):
    return {task["pillarId"] for task in result["tasks"]}


@pytest.mark.asyncio
async def test_generate_agent_enhanced_plan_preserves_full_committee_coverage(monkeypatch):
    proposals = [
        TaskProposal("P", "desc", "plan", "high", 10, "content", "why", {}, "navigate", "/content-planning-dashboard"),
        TaskProposal("G", "desc", "generate", "high", 10, "content", "why", {}, "navigate", "/blog-writer"),
        TaskProposal("Pu", "desc", "publish", "high", 10, "content", "why", {}, "navigate", "/scheduler-dashboard"),
        TaskProposal("A", "desc", "analyze", "high", 10, "content", "why", {}, "navigate", "/seo-dashboard"),
        TaskProposal("E", "desc", "engage", "high", 10, "content", "why", {}, "navigate", "/linkedin-writer"),
        TaskProposal("R", "desc", "remarket", "high", 10, "content", "why", {}, "navigate", "/facebook-writer"),
    ]

    async def _get_orchestrator(user_id):
        return _mock_orchestrator_with_agents(content_proposals=proposals)

    monkeypatch.setattr(svc, "build_grounding_context", lambda db, user_id, date: {})
    monkeypatch.setattr(svc.orchestration_service, "get_or_create_orchestrator", _get_orchestrator)

    result = await svc.generate_agent_enhanced_plan(db=None, user_id="u1", date="2026-01-01")

    assert _covered_pillars(result) == set(svc.PILLAR_IDS)
    assert len(result["tasks"]) == len(proposals)


@pytest.mark.asyncio
async def test_generate_agent_enhanced_plan_backfills_missing_committee_pillars(monkeypatch):
    proposals = [
        TaskProposal("P", "desc", "plan", "high", 10, "content", "why", {}, "navigate", "/content-planning-dashboard"),
        TaskProposal("G", "desc", "generate", "high", 10, "content", "why", {}, "navigate", "/blog-writer"),
    ]

    async def _get_orchestrator(user_id):
        return _mock_orchestrator_with_agents(content_proposals=proposals)

    monkeypatch.setattr(svc, "build_grounding_context", lambda db, user_id, date: {})
    monkeypatch.setattr(svc.orchestration_service, "get_or_create_orchestrator", _get_orchestrator)

    result = await svc.generate_agent_enhanced_plan(db=None, user_id="u1", date="2026-01-01")

    assert _covered_pillars(result) == set(svc.PILLAR_IDS)
    assert {"P", "G"}.issubset({task["title"] for task in result["tasks"]})


@pytest.mark.asyncio
async def test_generate_agent_enhanced_plan_full_fallback_path_still_covers_all_pillars(monkeypatch):
    async def _get_orchestrator(user_id):
        return _mock_orchestrator_with_agents()

    monkeypatch.setattr(svc, "build_grounding_context", lambda db, user_id, date: {})
    monkeypatch.setattr(svc.orchestration_service, "get_or_create_orchestrator", _get_orchestrator)
    monkeypatch.setattr(svc, "AgentActivityService", DummyActivity)

    def _raise_llm(*args, **kwargs):
        raise RuntimeError("LLM down")

    monkeypatch.setattr(svc, "llm_text_gen", _raise_llm)

    result = await svc.generate_agent_enhanced_plan(db=None, user_id="u1", date="2026-01-01")

    assert _covered_pillars(result) == set(svc.PILLAR_IDS)
    assert len(result["tasks"]) >= len(svc.PILLAR_IDS)


@pytest.mark.asyncio
async def test_generate_agent_enhanced_plan_strategy_plan_task_survives_dedupe_and_coverage(monkeypatch):
    content_proposals = [
        TaskProposal(
            "Review Strategic Goals",
            "desc",
            "plan",
            "medium",
            10,
            "ContentStrategyAgent",
            "why",
            {},
            "navigate",
            "/content-planning-dashboard",
        ),
    ]
    strategy_proposals = [
        TaskProposal(
            "Review Strategic Goals",
            "desc",
            "plan",
            "high",
            10,
            "StrategyArchitectAgent",
            "why",
            {},
            "navigate",
            "/content-planning-dashboard",
        ),
    ]

    async def _get_orchestrator(user_id):
        return _mock_orchestrator_with_agents(
            content_proposals=content_proposals,
            strategy_proposals=strategy_proposals,
        )

    monkeypatch.setattr(svc, "build_grounding_context", lambda db, user_id, date: {})
    monkeypatch.setattr(svc.orchestration_service, "get_or_create_orchestrator", _get_orchestrator)
    monkeypatch.setattr(svc, "TaskMemoryService", DummyMemoryService)

    result = await svc.generate_agent_enhanced_plan(db=None, user_id="u1", date="2026-01-01")

    assert _covered_pillars(result) == set(svc.PILLAR_IDS)
    plan_tasks = [task for task in result["tasks"] if task["pillarId"] == "plan"]
    assert any(
        task["title"] == "Review Strategic Goals"
        and task["metadata"].get("source_agent") == "StrategyArchitectAgent"
        for task in plan_tasks
    )
