"""
full_pipeline.py — All 6 STLC steps in a single agent loop.

Runs the complete pipeline end-to-end:
  1. Fetch work item
  2. Deduplication pre-flight (get_linked_test_cases + list_helix_tree)
  3. Create and link test cases
  4. Generate and attach Gherkin
  5. Capture live app context (requires APP_BASE_URL)
  6. Generate Playwright TypeScript
  6b. Write to Helix project on disk

Agents: qa-test-case-manager, qa-gherkin-generator,
        qa-playwright-generator, qa-helix-writer.

Triggered by:
  - event.extra["pipeline"] == "full"
  - env var STLC_FULL_PIPELINE=true
"""
from __future__ import annotations

import logging
import os

from ..agent_runner import run_agent_loop
from ..models import Platform, PipelineResult, WebhookEvent
from ._base import event_env, mcp_servers

logger = logging.getLogger("stlc.pipeline.full")

_AGENTS = (
    "qa-test-case-manager",
    "qa-gherkin-generator",
    "qa-playwright-generator",
    "qa-helix-writer",
)


def _task_prompt(event: WebhookEvent) -> str:
    wi_id      = event.work_item_id
    wi_type    = (event.work_item_type or "").lower()
    is_feature = wi_type == "feature"
    is_ado     = event.platform == Platform.ADO

    # ── Platform context ────────────────────────────────────────────────────
    if is_ado:
        platform_label = "ADO"
        platform_ctx   = (
            f"  Organisation: {event.organization_url}\n"
            f"  Project:      {event.project_name}\n"
        )
        if is_feature:
            fetch_step   = f"1. fetch_feature_hierarchy(work_item_id={wi_id})"
            attach_tool  = "attach_gherkin_to_feature"
        else:
            fetch_step   = f"1. fetch_work_item_for_gherkin(work_item_id={wi_id})"
            attach_tool  = "attach_gherkin_to_work_item"
    else:
        platform_label = "Jira"
        platform_ctx   = (
            f"  Cloud ID:  {event.cloud_id}\n"
            f"  Project:   {event.project_key}\n"
        )
        fetch_step  = f"1. fetch_work_item_for_gherkin(work_item_id={wi_id})"
        attach_tool = "attach_gherkin_to_work_item"

    # ── App credentials (event fields take priority over env vars) ──────────
    app_url      = event.app_base_url or os.environ.get("APP_BASE_URL", "")
    app_username = event.app_username or os.environ.get("APP_USERNAME", "")
    app_password = event.app_password or os.environ.get("APP_PASSWORD", "")

    # ── Helix root ──────────────────────────────────────────────────────────
    helix_root = event.helix_project_root

    # ── Deduplication pre-flight ────────────────────────────────────────────
    if helix_root:
        dedup_block = (
            f"DEDUPLICATION PRE-FLIGHT — run these BEFORE any creation steps:\n"
            f"  a) get_linked_test_cases(work_item_id={wi_id}) — store as existing_test_cases.\n"
            f"  b) list_helix_tree(helix_root={helix_root!r}) — check for files matching\n"
            f"     '*{wi_id}*' in both the 'features' AND 'steps' categories.\n"
            f"  If existing_test_cases is non-empty AND both Helix categories have matching files,\n"
            f"  this work item is fully covered — STOP and report the existing paths.\n\n"
        )
    else:
        dedup_block = (
            f"DEDUPLICATION PRE-FLIGHT — run this BEFORE any creation step:\n"
            f"  a) get_linked_test_cases(work_item_id={wi_id}) — store as existing_test_cases.\n\n"
        )

    # ── Step 3: test case creation ──────────────────────────────────────────
    feature_auto_confirm = (
        "     Auto-confirm if the tool returns confirmation_required=true.\n"
        if is_feature else ""
    )

    # ── Steps 5–6: live capture + code generation ───────────────────────────
    if app_url:
        capture_step = (
            f"5. capture_app_context(\n"
            f"     app_url={app_url!r},\n"
            f"     app_username={app_username!r},\n"
            f"     app_password={app_password!r},\n"
            f"     gherkin_content=<gherkin from step 4>)\n"
            f"   STOP if result.locator_source='gherkin-inferred' OR result.abort=true OR result.error is set.\n"
            f"   Only proceed to step 6 when locator_source='playwright-mcp-verified' AND context_map is non-empty.\n"
        )
        pw_step = (
            f"6. generate_playwright_code(\n"
            f"     gherkin_content=<gherkin from step 4>,\n"
            f"     context_map=<context_map from step 5>)\n"
            f"   Store the cache_key from the result.\n"
        )
        step_offset = 6
    else:
        capture_step = (
            "5. STOP — APP_BASE_URL is not configured.\n"
            "   A live context_map is required to generate correct locators.\n"
            "   Placeholder selectors are not acceptable output.\n"
            "   To unblock: set APP_BASE_URL (+ APP_USERNAME / APP_PASSWORD) in .env,\n"
            "   start 'npx @playwright/mcp@latest --port 8931', then re-trigger.\n"
            "   Do NOT call generate_playwright_code without a verified context_map.\n"
        )
        pw_step     = ""
        step_offset = 4

    # ── Steps 6b: Helix write ───────────────────────────────────────────────
    if helix_root and app_url:
        n = step_offset
        helix_steps = (
            f"{n+1}. inspect_helix_project(helix_root={helix_root!r})\n"
            f"   Proceed regardless of framework_state or missing_infra — do NOT stop after inspect.\n"
            f"{n+2}. write_helix_files(helix_root={helix_root!r}, cache_key=<cache_key from step {n}>)\n"
            f"   Pass cache_key directly — do NOT pass a files dict.\n"
            f"   This step is MANDATORY — the pipeline is not complete until write_helix_files succeeds.\n"
        )
    elif helix_root:
        # APP_BASE_URL missing — Playwright steps skipped, but still report Helix state
        helix_steps = (
            f"5b. inspect_helix_project(helix_root={helix_root!r})\n"
            f"    Report current state; no write_helix_files without generated code.\n"
        )
    else:
        helix_steps = ""

    # ── Stop conditions ─────────────────────────────────────────────────────
    stop_conditions = (
        "\nStop immediately if:\n"
        "  - fetch returns epic_not_supported or an error\n"
        "  - APP_BASE_URL is empty (steps 5+ require a live context_map)\n"
        "  - capture_app_context returns locator_source='gherkin-inferred', abort=true, or any error field\n"
        "  - capture_app_context returns an empty context_map\n"
        "  - generate_and_attach_gherkin returns status='duplicate' or 'already_attached'\n"
        f"  - Deduplication pre-flight finds existing .feature + .steps.ts for WI #{wi_id}\n"
        "\nNEVER call generate_playwright_code unless capture_app_context returned\n"
        "  locator_source='playwright-mcp-verified' with a non-empty context_map.\n"
        "  Gherkin-inferred locators reference elements that do not exist in the real app.\n"
    )

    return (
        f"You are a QA automation agent running in webhook mode — auto-confirm all prompts.\n\n"
        f"Task: Run the FULL STLC pipeline (test cases + Gherkin + Playwright + Helix) for\n"
        f"{platform_label} work item {wi_id}.\n"
        f"  Type:  {event.work_item_type}\n"
        f"  State: {event.state}\n"
        f"{platform_ctx}\n"
        f"{dedup_block}"
        f"Steps (execute in order):\n"
        f"{fetch_step}\n"
        f"   Store result as work_item_summary.\n"
        f"2. create_and_link_test_cases(work_item_id={wi_id}, ...)\n"
        f"   Derive test cases from work_item_summary acceptance criteria.\n"
        f"   SKIP if existing_test_cases from dedup pre-flight is non-empty.\n"
        f"{feature_auto_confirm}"
        f"3. {attach_tool}(work_item_id={wi_id}, ...)\n"
        f"   Generate BDD scenarios from work_item_summary.\n"
        f"   SKIP if Helix dedup pre-flight found a matching .feature file.\n"
        f"   Store gherkin_content from result.\n"
        f"4. validate_gherkin_content(gherkin_content=<from step 3>, scope='work_item')\n"
        f"   Proceed only if valid=true.\n"
        f"{capture_step}"
        f"{pw_step}"
        f"{helix_steps}"
        f"{stop_conditions}"
    )


async def run(event: WebhookEvent) -> PipelineResult:
    label = f"full-pipeline: wi={event.work_item_id}"
    success, error = await run_agent_loop(
        mcp_config=mcp_servers(*_AGENTS),
        prompt=_task_prompt(event),
        llm_provider=event.llm_provider,
        llm_model=event.llm_model,
        llm_api_key=event.llm_api_key,
        llm_base_url=event.llm_base_url,
        env=event_env(event),
        work_item_id=event.work_item_id,
    )
    if not success:
        return PipelineResult(success=False, steps=[label], error=error)
    return PipelineResult(success=True, steps=[label, "completed"])
