from __future__ import annotations

import os
from pathlib import Path

import pytest
from unified_agent import SandboxPolicy, UnifiedAgent

from pentestgpt_agent.agents import (
    EXECUTOR_INSTRUCTIONS,
    SUPERVISOR_INSTRUCTIONS,
    Executor,
    Supervisor,
)
from pentestgpt_agent.loop import PentestLoop
from pentestgpt_agent.memory import MemoryKernel, RunSpec, RunStatus
from pentestgpt_agent.trace import EpisodeRunner, TraceStore
from tests.support.local_target import local_template_target

pytestmark = [pytest.mark.live]

if os.getenv("PENTESTGPT_AGENT_LIVE") != "1":
    pytest.skip(
        "set PENTESTGPT_AGENT_LIVE=1 to run the live local-target smoke",
        allow_module_level=True,
    )


@pytest.mark.asyncio
async def test_real_agents_capture_the_local_template_flag(tmp_path: Path) -> None:
    backend = os.getenv("PENTESTGPT_AGENT_BACKEND", "claude")
    model = os.getenv("PENTESTGPT_AGENT_MODEL") or None
    with local_template_target() as benchmark:
        traces = TraceStore(tmp_path / "runs")
        supervisor = Supervisor(
            EpisodeRunner(
                UnifiedAgent(
                    backend,
                    workspace=tmp_path / "supervisor",
                    model=model,
                    sandbox=SandboxPolicy.FULL_ACCESS,
                    instructions=SUPERVISOR_INSTRUCTIONS,
                ),
                traces,
            ),
            max_turns=4,
        )
        executor = Executor(
            EpisodeRunner(
                UnifiedAgent(
                    backend,
                    workspace=tmp_path / "executor",
                    model=model,
                    sandbox=SandboxPolicy.FULL_ACCESS,
                    instructions=EXECUTOR_INSTRUCTIONS,
                ),
                traces,
            ),
            max_turns=12,
        )
        result = await PentestLoop(
            memory=MemoryKernel(tmp_path / "state.sqlite3"),
            supervisor=supervisor,
            executor=executor,
            traces=traces,
            max_decisions=8,
        ).run(
            RunSpec(
                run_id="live-local-target",
                goal="Capture the flag from this authorized local web application.",
                allowed_targets=(benchmark.url,),
            )
        )

    assert result.status is RunStatus.COMPLETED
    assert any(benchmark.flag in observation.statement for observation in result.observations)
