"""
통합 테스트: scripts/g3_independent_verifier.py
task-1837_5.1 - 닌기르수 작성
"""

import json
import sys

sys.path.insert(0, "/home/jay/workspace/scripts")
import g3_independent_verifier as g3v


# ── 1. load_report ──────────────────────────────────────────────────────────

def test_load_report_returns_content_when_exists(tmp_path, monkeypatch):
    """보고서 파일이 존재하면 내용을 반환해야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)
    expected = "# 테스트 보고서\n내용입니다."
    (reports_dir / "task-load-test.md").write_text(expected, encoding="utf-8")

    result = g3v.load_report("task-load-test")
    assert result == expected


def test_load_report_returns_none_when_missing(tmp_path, monkeypatch):
    """보고서 파일이 없으면 None을 반환해야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)

    result = g3v.load_report("task-nonexistent")
    assert result is None


def test_load_report_utf8_korean(tmp_path, monkeypatch):
    """UTF-8 한글 내용을 정확히 반환해야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)
    korean = "## 수정 파일별 검증 상태\n\n| 파일 | 변경 내용 | grep 검증 | 상태 |"
    (reports_dir / "task-korean.md").write_text(korean, encoding="utf-8")

    result = g3v.load_report("task-korean")
    assert result == korean


# ── 2. parse_verification_table ──────────────────────────────────────────────

def test_parse_verification_table_extracts_entries():
    """마크다운 테이블에서 file_path/keyword/status를 올바르게 추출해야 한다."""
    report = """## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/foo.py | 함수 추가 | grep "def foo" OK | verified |
| utils/bar.py | 버그 수정 | grep "fix_bug" OK | verified |
"""
    entries = g3v.parse_verification_table(report)
    assert len(entries) == 2
    assert entries[0]["file_path"] == "scripts/foo.py"
    assert entries[0]["keyword"] == "def foo"
    assert entries[0]["status"] == "verified"
    assert entries[1]["file_path"] == "utils/bar.py"
    assert entries[1]["keyword"] == "fix_bug"


def test_parse_verification_table_no_table_returns_empty():
    """'수정 파일별 검증 상태' 테이블이 없으면 빈 리스트를 반환해야 한다."""
    report = "# 보고서\n## 작업 완료\n내용만 있고 테이블 없음."
    entries = g3v.parse_verification_table(report)
    assert entries == []


def test_parse_verification_table_skips_header_and_separator():
    """헤더 행과 구분선은 항목으로 파싱되지 않아야 한다."""
    report = """## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/actual.py | 실제 변경 | grep "actual_func" OK | verified |
"""
    entries = g3v.parse_verification_table(report)
    assert len(entries) == 1
    assert entries[0]["file_path"] == "scripts/actual.py"


def test_parse_verification_table_no_keyword_when_no_grep():
    """grep 검증 셀에 grep 키워드 형식이 없으면 keyword는 None이어야 한다."""
    report = """## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| scripts/no_grep.py | 파일 생성 | N/A | verified |
"""
    entries = g3v.parse_verification_table(report)
    assert len(entries) == 1
    assert entries[0]["keyword"] is None


# ── 3. check_file_existence ──────────────────────────────────────────────────

def test_check_file_existence_pass_when_all_exist(tmp_path, monkeypatch):
    """모든 파일이 존재하면 status='PASS', missing=[]를 반환해야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    existing = tmp_path / "scripts" / "existing.py"
    existing.parent.mkdir(parents=True, exist_ok=True)
    existing.write_text("def foo(): pass", encoding="utf-8")

    entries = [{"file_path": str(existing), "description": "테스트", "keyword": None, "status": "verified"}]
    status, missing = g3v.check_file_existence(entries)
    assert status == "PASS"
    assert missing == []


def test_check_file_existence_fail_when_file_missing(tmp_path, monkeypatch):
    """파일이 없으면 status='FAIL', missing에 파일명이 포함되어야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    entries = [{"file_path": "scripts/missing_file.py", "description": "없는 파일", "keyword": None, "status": "verified"}]
    status, missing = g3v.check_file_existence(entries)
    assert status == "FAIL"
    assert "scripts/missing_file.py" in missing


def test_check_file_existence_mixed(tmp_path, monkeypatch):
    """일부 파일이 있고 일부가 없을 때 missing 목록이 정확해야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    existing = tmp_path / "exists.py"
    existing.write_text("pass", encoding="utf-8")

    entries = [
        {"file_path": str(existing), "description": "있는 파일", "keyword": None, "status": "verified"},
        {"file_path": "no_such_file.py", "description": "없는 파일", "keyword": None, "status": "verified"},
    ]
    status, missing = g3v.check_file_existence(entries)
    assert status == "FAIL"
    assert len(missing) == 1
    assert "no_such_file.py" in missing[0]


# ── 4. resolve_file_path ─────────────────────────────────────────────────────

def test_resolve_file_path_strips_line_number(tmp_path, monkeypatch):
    """'path:123' 형식에서 라인번호를 제거하고 순수 경로를 반환해야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    result = g3v.resolve_file_path("/absolute/path/file.py:42")
    assert str(result) == "/absolute/path/file.py"
    assert "42" not in str(result)


def test_resolve_file_path_relative_to_absolute(tmp_path, monkeypatch):
    """상대 경로는 WORKSPACE_ROOT 기준 절대 경로로 변환되어야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    result = g3v.resolve_file_path("scripts/some_file.py")
    assert result.is_absolute()
    assert str(tmp_path) in str(result)
    assert "scripts/some_file.py" in str(result)


def test_resolve_file_path_absolute_unchanged(tmp_path, monkeypatch):
    """절대 경로는 그대로 반환되어야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    abs_path = "/home/jay/workspace/scripts/tool.py"
    result = g3v.resolve_file_path(abs_path)
    assert str(result) == abs_path


def test_resolve_file_path_colon_only_at_end_with_digits(tmp_path, monkeypatch):
    """path:숫자 형식만 라인번호로 인식, 중간 콜론은 제거하지 않아야 한다."""
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    # "path:123" → "path" 분리
    result = g3v.resolve_file_path("scripts/file.py:100")
    assert not str(result).endswith(":100")
    assert "file.py" in str(result)


# ── 5. main() — E2E 테스트 ───────────────────────────────────────────────────

def test_main_exits_0_when_no_report(tmp_path, monkeypatch):
    """보고서가 없으면 main()은 exit 1을 발생시켜야 한다 (report not found → FAIL)."""
    import pytest
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    # memory/reports 디렉토리는 있지만 파일 없음
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)
    (tmp_path / "memory" / "events").mkdir(parents=True, exist_ok=True)

    monkeypatch.setattr(sys, "argv", ["g3v.py", "--task-id", "task-no-report-e2e"])
    with pytest.raises(SystemExit) as exc_info:
        g3v.main()
    assert exc_info.value.code == 1


def test_main_exits_1_when_report_no_table_low_quality(tmp_path, monkeypatch):
    """보고서가 있지만 검증 테이블 없고 품질 기준 미달이면 FAIL → exit 1이어야 한다."""
    import pytest
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)
    # 테이블 없고 짧은 보고서 (V-5: 품질 미달)
    (reports_dir / "task-skip-e2e.md").write_text("# 보고서\n내용만 있음", encoding="utf-8")

    monkeypatch.setattr(sys, "argv", ["g3v.py", "--task-id", "task-skip-e2e"])
    with pytest.raises(SystemExit) as exc_info:
        g3v.main()
    assert exc_info.value.code == 1


def test_main_exits_0_when_report_no_table_good_quality(tmp_path, monkeypatch):
    """보고서가 있고 검증 테이블 없지만 품질 기준 충족이면 SKIP → exit 0이어야 한다."""
    import pytest
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)
    # SCQA 패턴 2개 + 200자 이상 (V-5 통과)
    good_report = """# task-skip-quality 보고서

**S**: 상황 설명입니다. 기존 시스템에서 특정 기능이 필요했습니다. 여러 모듈 간의 의존성으로 인해 복잡한 구조를 갖고 있었습니다.
**C**: 복잡도가 높아서 추가 분석이 필요했습니다. 기존 코드의 문제점을 파악하고 개선 방향을 수립했습니다.
**Q**: 어떻게 해결할 것인가? 어떤 접근 방식이 가장 효율적인가?
**A**: 다음과 같이 해결했습니다. 코드를 수정하고 테스트를 추가하여 검증을 완료했습니다. 전체 테스트 통과 확인. 리팩터링을 통해 가독성과 유지보수성을 향상시켰습니다.
"""
    (reports_dir / "task-skip-quality.md").write_text(good_report, encoding="utf-8")

    monkeypatch.setattr(sys, "argv", ["g3v.py", "--task-id", "task-skip-quality"])
    with pytest.raises(SystemExit) as exc_info:
        g3v.main()
    assert exc_info.value.code == 0


def test_main_exits_0_when_all_files_exist(tmp_path, monkeypatch):
    """보고서 + 파일 모두 존재하면 exit 0이어야 한다."""
    import pytest
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)

    # 실제 파일 생성
    scripts_dir = tmp_path / "scripts"
    scripts_dir.mkdir(parents=True, exist_ok=True)
    target_file = scripts_dir / "real_file.py"
    target_file.write_text("def actual_func(): pass", encoding="utf-8")

    report_content = f"""# 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| {str(target_file)} | 함수 추가 | grep "actual_func" OK | verified |
"""
    (reports_dir / "task-pass-e2e.md").write_text(report_content, encoding="utf-8")

    monkeypatch.setattr(sys, "argv", ["g3v.py", "--task-id", "task-pass-e2e"])
    with pytest.raises(SystemExit) as exc_info:
        g3v.main()
    assert exc_info.value.code == 0


def test_main_exits_1_when_file_missing(tmp_path, monkeypatch):
    """보고서는 있지만 파일이 누락되면 exit 1이어야 한다."""
    import pytest
    monkeypatch.setattr(g3v, "WORKSPACE_ROOT", str(tmp_path))
    reports_dir = tmp_path / "memory" / "reports"
    reports_dir.mkdir(parents=True, exist_ok=True)
    (tmp_path / "memory" / "events").mkdir(parents=True, exist_ok=True)

    report_content = f"""# 보고서

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| {str(tmp_path)}/scripts/missing_file.py | 함수 추가 | grep "func" OK | verified |
"""
    (reports_dir / "task-fail-e2e.md").write_text(report_content, encoding="utf-8")

    monkeypatch.setattr(sys, "argv", ["g3v.py", "--task-id", "task-fail-e2e"])
    with pytest.raises(SystemExit) as exc_info:
        g3v.main()
    assert exc_info.value.code == 1
