"""Integration test for refinement phase with fake agents."""

import asyncio
import json
from pathlib import Path

from deliberate.adapters.fake_adapter import FakeAdapter
from deliberate.config import (
    AgentConfig,
    DeliberateConfig,
    ExecutionConfig,
    RefinementConfig,
    ReviewConfig,
    WorkflowConfig,
)
from deliberate.orchestrator import Orchestrator


class LowScoringCriticAdapter(FakeAdapter):
    """Fake critic that gives low scores to trigger refinement."""

    async def call(self, prompt: str, **kwargs):
        """Return low scores to trigger refinement."""
        response = await super().call(prompt, **kwargs)

        # Override the critic response with low scores
        if self.behavior == "critic":
            response.content = json.dumps(
                {
                    "scores": {
                        "correctness": 4,
                        "code_quality": 5,
                        "completeness": 4,
                        "risk": 6,
                    },
                    "overall": 4.75,
                    "recommendation": "revise",
                    "reasoning": f"Needs improvement. Analysis by {self.name}. "
                    f"Several issues found that should be addressed.",
                },
                indent=2,
            )

        return response


async def test_refinement_phase():
    """Test refinement phase with fake agents that produce low-quality results initially."""

    # Get current directory as repo root
    repo_root = Path.cwd()

    # Create config with refinement enabled
    from deliberate.config import PlanningConfig

    config = DeliberateConfig(
        agents={
            "executor1": AgentConfig(
                type="fake",
                behavior="echo",  # Just echoes back, will get low scores
                capabilities=["executor"],
            ),
            "reviewer1": AgentConfig(
                type="fake",
                behavior="critic",  # Critical reviewer, gives low scores
                capabilities=["reviewer"],
            ),
        },
        workflow=WorkflowConfig(
            planning=PlanningConfig(enabled=False),  # Skip planning for simplicity
            execution=ExecutionConfig(
                enabled=True,
                agents=["executor1"],
            ),
            review=ReviewConfig(
                enabled=True,
                agents=["reviewer1"],
            ),
            refinement=RefinementConfig(
                enabled=True,
                min_confidence=0.5,  # Low threshold to trigger refinement
                min_winner_score=0.7,  # High threshold to trigger refinement
                max_iterations=2,
                min_improvement_threshold=0.01,
            ),
        ),
    )

    # Create orchestrator with repo_root
    orchestrator = Orchestrator(config, repo_root)

    # Replace the reviewer adapter with our low-scoring critic
    orchestrator.adapters["reviewer1"] = LowScoringCriticAdapter(
        name="reviewer1",
        behavior="critic",
    )
    # Also update the review phase to use the custom adapter
    orchestrator.review.adapters["reviewer1"] = orchestrator.adapters["reviewer1"]

    # Run a simple task
    task = "Create a simple hello world function in Python"

    print("\n" + "="*80)
    print("Testing Refinement Phase Integration")
    print("="*80)
    print(f"\nTask: {task}")
    print(f"Executor: {config.workflow.execution.agents}")
    print(f"Reviewer: {config.workflow.review.agents}")
    print(f"Refinement Enabled: {config.workflow.refinement.enabled}")
    print(f"Min Winner Score: {config.workflow.refinement.min_winner_score}")
    print()

    # Run the orchestrator
    result = await orchestrator.run(task)

    # HACK: For testing with fake agents, add fake diffs to execution results
    # Real agents produce actual diffs via git worktrees
    for exec_result in result.execution_results:
        if not exec_result.diff:
            exec_result.diff = "--- a/hello.py\n+++ b/hello.py\n@@ -0,0 +1,2 @@\n+def hello():\n+    print('Hello, World!')"

    # Re-run review and refinement with patched results
    if result.execution_results and not result.reviews:
        # Review phase was skipped due to missing diffs, run it manually
        reviews, vote_result = await orchestrator.review.run(task, result.execution_results)
        result.reviews = reviews
        result.vote_result = vote_result

        # Check if refinement should trigger
        if orchestrator.config.workflow.refinement.enabled and vote_result:
            from deliberate.phases.refinement import RefinementOrchestrator

            refinement_orch = RefinementOrchestrator(
                config=orchestrator.config.workflow.refinement,
                agents=list(orchestrator.adapters.values()),
                budget_tracker=orchestrator.budget,
                worktree_mgr=orchestrator.worktrees,
            )

            should_refine = await refinement_orch.should_trigger(vote_result, reviews)
            if should_refine:
                result.refinement_triggered = True
                result.refinement_iterations = await refinement_orch.run_refinement_loop(
                    initial_results=result.execution_results,
                    initial_reviews=reviews,
                    initial_vote=vote_result,
                    task_description=task,
                )

                if result.refinement_iterations:
                    final_iteration = result.refinement_iterations[-1]
                    result.vote_result = final_iteration.vote_result
                    result.reviews = final_iteration.reviews
                    result.final_improvement = sum(
                        it.improvement_delta for it in result.refinement_iterations
                    )

    print("\n" + "="*80)
    print("Results")
    print("="*80)
    print(f"Success: {result.success}")
    print(f"Execution Results: {len(result.execution_results)}")
    print(f"Reviews: {len(result.reviews)}")
    print(f"Refinement Triggered: {result.refinement_triggered}")
    print(f"Refinement Iterations: {len(result.refinement_iterations)}")
    print(f"Final Improvement: {result.final_improvement:.3f}")

    if result.vote_result:
        print(f"\nFinal Vote:")
        print(f"  Winner: {result.vote_result.winner_id}")
        print(f"  Confidence: {result.vote_result.confidence:.3f}")
        print(f"  Scores: {result.vote_result.scores}")

    if result.refinement_iterations:
        print(f"\nRefinement Iterations:")
        for i, iteration in enumerate(result.refinement_iterations, 1):
            print(f"\n  Iteration {i}:")
            print(f"    Improvement Delta: {iteration.improvement_delta:.3f}")
            print(f"    Tokens Used: {iteration.tokens_used}")
            print(f"    Issues: {len(iteration.feedback.issues)}")
            print(f"    Suggestions: {len(iteration.feedback.suggestions)}")
            print(f"    Reviews in iteration: {len(iteration.reviews)}")

    # Get budget breakdown by phase
    phase_usage = orchestrator.budget.get_all_phase_usage()
    print(f"\nBudget Usage by Phase:")
    for phase, usage in phase_usage.items():
        print(f"  {phase}: {usage.tokens} tokens, ${usage.cost_usd:.4f}")

    print("\n" + "="*80)
    print("Test Complete!")
    print("="*80 + "\n")

    return result


if __name__ == "__main__":
    result = asyncio.run(test_refinement_phase())

    # Basic assertions
    assert result.success, "Orchestrator run should succeed"
    assert len(result.execution_results) > 0, "Should have execution results"
    assert len(result.reviews) > 0, "Should have reviews"

    print("✅ All basic assertions passed!")
