#!/usr/bin/env python3
"""
tests/test_o1_rebuttal.py — O-1 Rebuttal & Re-adjudication Protocol regression suite (V-1..V-10).
"""

import os
import subprocess
import pytest

REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
RUN_LOOP_SH = os.path.join(REPO_ROOT, ".agents", "skills", "multi-agent-mux-loop", "scripts", "run_loop.sh")
RULES_MD = os.path.join(REPO_ROOT, ".agents", "MULTI_AGENT_RULES.md")
RULES_KO_MD = os.path.join(REPO_ROOT, ".agents", "MULTI_AGENT_RULES.ko.md")
SKILL_MD = os.path.join(REPO_ROOT, ".agents", "skills", "multi-agent-mux-loop", "SKILL.md")
IMPROVEMENTS_MD = os.path.join(REPO_ROOT, "IMPROVEMENTS.md")


def _get_run_loop_helpers():
    """Extract helper functions from run_loop.sh to run standalone in bash tests."""
    with open(RUN_LOOP_SH, "r", encoding="utf-8") as f:
        content = f.read()

    # Extract has_tag_line and extract_tag_values definitions
    has_tag_line_code = content.split("has_tag_line() {")[1].split("extract_tag_values() {")[0]
    extract_tag_values_code = content.split("extract_tag_values() {")[1].split("find_report() {")[0]

    return f"""
has_tag_line() {{
{has_tag_line_code}
extract_tag_values() {{
{extract_tag_values_code}
"""


def test_v1_has_tag_line_single_and_first_line(tmp_path):
    """V-1: has_tag_line matches tag on line 1 of report file."""
    report_file = tmp_path / "report-final.md"
    report_file.write_text("[ESCALATE: PLANNER]\nDetailed feedback follows...")

    helpers = _get_run_loop_helpers()
    cmd = f"""
{helpers}
has_tag_line "{report_file}" "ESCALATE: PLANNER"
"""
    res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True)
    assert res.returncode == 0


def test_v2_extract_tag_values_multiple_rebuts(tmp_path):
    """V-2: extract_tag_values extracts all [REBUT: target] tags."""
    report_file = tmp_path / "report-final.md"
    report_file.write_text("[REBUT: reviewer_a]\n[REBUT: reviewer_b]\nContent...")

    helpers = _get_run_loop_helpers()
    cmd = f"""
{helpers}
extract_tag_values "{report_file}" "REBUT"
"""
    res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True)
    assert res.returncode == 0
    lines = [line.strip() for line in res.stdout.splitlines() if line.strip()]
    assert lines == ["reviewer_a", "reviewer_b"]


def test_v3_rebut_option_parsing_and_budget():
    """V-3: --max-rebut N option parsing and error handling."""
    # Check help
    res_help = subprocess.run(["bash", RUN_LOOP_SH, "--help"], capture_output=True, text=True)
    assert "--max-rebut N" in res_help.stdout or "--max-rebut N" in res_help.stderr

    # Check invalid value
    res_invalid = subprocess.run(["bash", RUN_LOOP_SH, "--max-rebut", "abc"], capture_output=True, text=True)
    assert res_invalid.returncode != 0
    assert "ERROR: --max-rebut requires a non-negative integer." in res_invalid.stdout or "ERROR: --max-rebut requires a non-negative integer." in res_invalid.stderr


def test_v4_rebuttal_deduplication():
    """V-4: REBUT_TARGETS deduplication logic."""
    cmd = """
    FAIL_REVS=("rev1" "rev2")
    REBUT_TARGETS=()
    INPUT_TAGS=("rev1" "rev1" "rev2" "rev3")

    for _t in "${INPUT_TAGS[@]}"; do
        for _fv in "${FAIL_REVS[@]}"; do
            [ "$_t" = "$_fv" ] || continue
            _dup=0
            for _e in ${REBUT_TARGETS[@]+"${REBUT_TARGETS[@]}"}; do
                if [ "$_e" = "$_t" ]; then _dup=1; break; fi
            done
            [ "$_dup" -eq 0 ] && REBUT_TARGETS+=("$_t")
            break
        done
    done
    echo "${REBUT_TARGETS[*]}"
    """
    res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True)
    assert res.returncode == 0
    assert res.stdout.strip() == "rev1 rev2"


def test_v5_fail_closed_on_missing_sustained(tmp_path):
    """V-5: Non-SUSTAINED adjudication report fails closed (objection stands)."""
    report_overruled = tmp_path / "report_overruled.md"
    report_overruled.write_text("[ADJUDICATION: OVERRULED]\nObjection maintained.")

    report_empty = tmp_path / "report_empty.md"
    report_empty.write_text("No explicit adjudication tag present.")

    helpers = _get_run_loop_helpers()
    cmd = f"""
{helpers}
if has_tag_line "{report_overruled}" "ADJUDICATION: SUSTAINED"; then echo "SUSTAINED"; else echo "OVERRULED"; fi
if has_tag_line "{report_empty}" "ADJUDICATION: SUSTAINED"; then echo "SUSTAINED"; else echo "OVERRULED"; fi
"""
    res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True)
    assert res.returncode == 0
    lines = res.stdout.splitlines()
    assert lines[0] == "OVERRULED"
    assert lines[1] == "OVERRULED"


def test_v6_bash_3_2_empty_array_safety():
    """V-6: Empty array expansion with set -u on bash 3.2 syntax."""
    cmd = """
    set -euo pipefail
    declare -a EMPTY_ARR=()
    for item in ${EMPTY_ARR[@]+"${EMPTY_ARR[@]}"}; do
        echo "$item"
    done
    echo "SUCCESS"
    """
    res = subprocess.run(["bash", "-c", cmd], capture_output=True, text=True)
    assert res.returncode == 0
    assert "SUCCESS" in res.stdout


def test_v7_rules_docs_contain_section_3_1():
    """V-7: MULTI_AGENT_RULES.md and MULTI_AGENT_RULES.ko.md contain section 3.1."""
    with open(RULES_MD, "r", encoding="utf-8") as f:
        content_en = f.read()
    with open(RULES_KO_MD, "r", encoding="utf-8") as f:
        content_ko = f.read()

    assert "### 3.1 Rebuttal & Adjudication Protocol" in content_en
    assert "### 3.1 Rebuttal & Adjudication Protocol" in content_ko
    assert "[REBUT:" in content_en and "[ADJUDICATION: SUSTAINED]" in content_en
    assert "[REBUT:" in content_ko and "[ADJUDICATION: SUSTAINED]" in content_ko


def test_v8_skill_md_contains_max_rebut():
    """V-8: multi-agent-mux-loop/SKILL.md contains --max-rebut documentation."""
    with open(SKILL_MD, "r", encoding="utf-8") as f:
        content = f.read()

    assert "`--max-rebut`" in content
    assert "Rebuttal & Adjudication Protocol" in content


def test_v9_per_iteration_budget_reset():
    """V-9: run_loop.sh resets REBUT_BUDGET per iteration while tracking REBUT_TOTAL_BUDGET."""
    with open(RUN_LOOP_SH, "r", encoding="utf-8") as f:
        content = f.read()

    assert 'REBUT_BUDGET="$MAX_REBUT"' in content
    assert "REBUT_TOTAL_BUDGET=$((MAX_REBUT * MAX_LOOP))" in content
    assert "REBUT_TOTAL_BUDGET=$((REBUT_TOTAL_BUDGET - 1))" in content


def test_v10_improvements_md_o1_completed():
    """V-10: IMPROVEMENTS.md has O-1 moved to completed tasks section."""
    with open(IMPROVEMENTS_MD, "r", encoding="utf-8") as f:
        content = f.read()

    assert "O-1" in content
    assert "[O-1] Rebuttal & Re-adjudication Protocol" in content or "O-1: 타당하지 않은 리뷰 피드백 거부/반론 프로토콜 미지원" in content
