"""
regression: test_stash_origin_audit_metadata_format.py
task: task-2570 TODO-4
작성자: 하누만(테스터)

검증 목표:
1. spec 파일 존재 + 필수 키워드 검증
2. finish-task.sh의 stash_origin_metadata 필드 존재 검증 (BEFORE/AFTER 블록 각각)
3. 5개 표준 source 카테고리 중 5개 이상 spec에 명시 검증
"""

import re
from pathlib import Path

import pytest

# 워크스페이스 루트 (worktree 기준)
WORKTREE_ROOT = Path(__file__).resolve().parents[2]
SPEC_FILE = WORKTREE_ROOT / "memory" / "specs" / "stash-origin-audit.md"
FINISH_TASK_SH = WORKTREE_ROOT / "scripts" / "finish-task.sh"

REQUIRED_KEYWORDS = [
    "task_id",
    "source",
    "reason",
    "caller_script",
    "timestamp",
    "[task-",
    "[source=",
]

STANDARD_SOURCE_CATEGORIES = [
    "finish-task",
    "pre-task",
    "quarantine",
    "wip",
    "other-files",
    "unknown",
]


# ---------------------------------------------------------------------------
# 1. spec 파일 존재 + 필수 키워드 검증
# ---------------------------------------------------------------------------

def test_spec_file_exists():
    """spec 파일(stash-origin-audit.md)이 존재해야 한다."""
    assert SPEC_FILE.exists(), f"spec 파일이 없음: {SPEC_FILE}"
    assert SPEC_FILE.is_file(), f"spec 파일이 파일이 아님: {SPEC_FILE}"


def test_spec_file_is_nonempty():
    """spec 파일이 비어있지 않아야 한다."""
    content = SPEC_FILE.read_text(encoding="utf-8")
    assert len(content.strip()) > 0, "spec 파일이 비어있음"


@pytest.mark.parametrize("keyword", REQUIRED_KEYWORDS)
def test_spec_contains_required_keyword(keyword):
    """spec 파일에 필수 키워드가 존재해야 한다."""
    content = SPEC_FILE.read_text(encoding="utf-8")
    assert keyword in content, (
        f"spec 파일에 필수 키워드 '{keyword}'가 없음\n"
        f"파일: {SPEC_FILE}"
    )


# ---------------------------------------------------------------------------
# 2. finish-task.sh의 stash_origin_metadata 필드 존재 검증 (BEFORE/AFTER 블록)
# ---------------------------------------------------------------------------

def test_finish_task_sh_exists():
    """finish-task.sh 파일이 존재해야 한다."""
    assert FINISH_TASK_SH.exists(), f"finish-task.sh가 없음: {FINISH_TASK_SH}"
    assert FINISH_TASK_SH.is_file()


def test_finish_task_sh_stash_audit_before_block_has_metadata():
    """
    finish-task.sh의 _STASH_AUDIT_BEFORE 관련 블록에
    stash_origin_metadata 필드가 존재해야 한다.
    """
    content = FINISH_TASK_SH.read_text(encoding="utf-8")
    assert "_STASH_AUDIT_BEFORE" in content, (
        "finish-task.sh에 _STASH_AUDIT_BEFORE 변수가 없음"
    )

    # BEFORE 블록 추출 — AFTER 블록 이전까지
    before_idx = content.find("_STASH_AUDIT_BEFORE")
    after_idx = content.find("_STASH_AUDIT_AFTER")
    assert before_idx != -1 and after_idx != -1

    before_section = content[before_idx:after_idx]
    assert "stash_origin_metadata" in before_section, (
        "BEFORE 블록에 stash_origin_metadata 필드가 없음\n"
        f"파일: {FINISH_TASK_SH}"
    )


def test_finish_task_sh_stash_audit_after_block_has_metadata():
    """
    finish-task.sh의 _STASH_AUDIT_AFTER 관련 블록에
    stash_origin_metadata 필드가 존재해야 한다.
    """
    content = FINISH_TASK_SH.read_text(encoding="utf-8")
    assert "_STASH_AUDIT_AFTER" in content, (
        "finish-task.sh에 _STASH_AUDIT_AFTER 변수가 없음"
    )

    # AFTER 블록 추출 — 마지막 _STASH_AUDIT_AFTER 이후 섹션
    after_idx = content.rfind("_STASH_AUDIT_AFTER")
    after_section = content[after_idx:]
    assert "stash_origin_metadata" in after_section, (
        "AFTER 블록에 stash_origin_metadata 필드가 없음\n"
        f"파일: {FINISH_TASK_SH}"
    )


def test_finish_task_sh_both_audit_blocks_present():
    """_STASH_AUDIT_BEFORE 와 _STASH_AUDIT_AFTER 가 모두 존재해야 한다."""
    content = FINISH_TASK_SH.read_text(encoding="utf-8")
    assert "_STASH_AUDIT_BEFORE" in content, "_STASH_AUDIT_BEFORE 없음"
    assert "_STASH_AUDIT_AFTER" in content, "_STASH_AUDIT_AFTER 없음"


def test_finish_task_sh_stash_origin_metadata_field_count():
    """
    finish-task.sh에 stash_origin_metadata 필드가 최소 2번 등장해야 한다
    (BEFORE 블록 + AFTER 블록 각각).
    """
    content = FINISH_TASK_SH.read_text(encoding="utf-8")
    occurrences = content.count("stash_origin_metadata")
    assert occurrences >= 2, (
        f"stash_origin_metadata 가 {occurrences}회만 등장 (최소 2회 필요)"
    )


def test_finish_task_sh_metadata_source_field():
    """stash_origin_metadata에 source 필드가 포함되어 있어야 한다."""
    content = FINISH_TASK_SH.read_text(encoding="utf-8")
    # "source": "finish-task" 패턴 검증
    pattern = re.compile(r'"source"\s*:\s*"finish-task"')
    assert pattern.search(content), (
        'stash_origin_metadata에 "source": "finish-task" 패턴이 없음'
    )


# ---------------------------------------------------------------------------
# 3. spec에 5개 이상의 표준 source 카테고리 명시 검증
# ---------------------------------------------------------------------------

def test_spec_contains_at_least_five_source_categories():
    """
    spec 파일에 표준 source 카테고리가 최소 5개 이상 명시되어 있어야 한다.
    (finish-task / pre-task / quarantine / wip / other-files / unknown 중 5개+)
    """
    content = SPEC_FILE.read_text(encoding="utf-8")
    found = [cat for cat in STANDARD_SOURCE_CATEGORIES if cat in content]
    assert len(found) >= 5, (
        f"spec에 source 카테고리가 {len(found)}개만 존재 (최소 5개 필요)\n"
        f"발견된 카테고리: {found}\n"
        f"전체 카테고리: {STANDARD_SOURCE_CATEGORIES}"
    )


@pytest.mark.parametrize("category", STANDARD_SOURCE_CATEGORIES)
def test_spec_contains_source_category(category):
    """각 표준 source 카테고리가 spec에 명시되어 있어야 한다."""
    content = SPEC_FILE.read_text(encoding="utf-8")
    assert category in content, (
        f"spec 파일에 source 카테고리 '{category}'가 없음"
    )


def test_spec_source_table_structure():
    """spec에 source 분류 테이블 헤더(| source 값 |)가 존재해야 한다."""
    content = SPEC_FILE.read_text(encoding="utf-8")
    # Markdown 테이블에서 source 컬럼 헤더 확인
    assert "source" in content.lower(), "spec에 'source' 키워드가 없음"
    # 테이블 구조: | ... | ... | 형태
    table_row_pattern = re.compile(r"\|.+\|.+\|")
    assert table_row_pattern.search(content), "spec에 Markdown 테이블 구조가 없음"
