#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "pydantic>=2.0",
# ]
# ///
"""Verify NNNN-tasks.json structure and content."""

import json
import sys
from pathlib import Path

from pydantic import BaseModel, Field, field_validator


class Task(BaseModel):
    """A single task (user story, bug fix, enhancement, etc.)."""

    id: str = Field(description="Task ID, e.g., US-001, BUG-001, TASK-001")
    title: str = Field(description="Short task title")
    description: str = Field(description="Task description (user story format or plain)")
    acceptanceCriteria: list[str] = Field(  # noqa: N815
        description="List of verifiable criteria", min_length=1
    )
    priority: int = Field(description="Execution order", ge=1)
    passes: bool = Field(description="Whether task is complete", default=False)
    notes: str = Field(description="Optional notes", default="")

    @field_validator("id")
    @classmethod
    def validate_id(cls, v: str) -> str:
        valid_prefixes = ("US-", "BUG-", "FIX-", "TASK-", "ENH-")
        if not any(v.startswith(prefix) for prefix in valid_prefixes):
            raise ValueError(
                f"ID must start with one of {valid_prefixes}, got: {v}"
            )
        return v

    @field_validator("acceptanceCriteria")
    @classmethod
    def validate_criteria(cls, v: list[str]) -> list[str]:
        vague_terms = ["works correctly", "good ux", "handles edge cases", "easily"]
        for criterion in v:
            lower = criterion.lower()
            for term in vague_terms:
                if term in lower:
                    raise ValueError(
                        f"Criterion too vague (contains '{term}'): {criterion}"
                    )
        return v


class TasksFile(BaseModel):
    """The NNNN-tasks.json structure."""

    prd: str = Field(description="Source PRD filename (with .md extension)")
    branchName: str = Field(description="Git branch name for this feature")  # noqa: N815
    description: str = Field(description="Feature description")
    tasks: list[Task] = Field(description="List of tasks", min_length=1)

    @field_validator("prd")
    @classmethod
    def validate_prd(cls, v: str) -> str:
        if not v.endswith(".md"):
            raise ValueError(f"PRD field must end with .md, got: {v}")
        return v

    @field_validator("branchName")
    @classmethod
    def validate_branch_name(cls, v: str) -> str:
        if " " in v:
            raise ValueError(f"Branch name cannot contain spaces: {v}")
        if not v.islower() and "-" not in v and "_" not in v:
            raise ValueError(f"Branch name should be kebab-case: {v}")
        return v

    @field_validator("tasks")
    @classmethod
    def validate_task_order(cls, v: list[Task]) -> list[Task]:
        priorities = [t.priority for t in v]
        if priorities != sorted(priorities):
            raise ValueError(f"Tasks must be ordered by priority. Got: {priorities}")

        ids = [t.id for t in v]
        if len(ids) != len(set(ids)):
            raise ValueError(f"Duplicate task IDs found: {ids}")

        return v


def verify_tasks(file_path: Path) -> bool:
    """Verify a NNNN-tasks.json file."""
    if not file_path.exists():
        print(f"Error: File not found: {file_path}")
        return False

    try:
        with open(file_path) as f:
            data = json.load(f)
    except json.JSONDecodeError as e:
        print(f"Error: Invalid JSON: {e}")
        return False

    try:
        tasks_file = TasksFile(**data)
    except Exception as e:
        print(f"Error: Validation failed: {e}")
        return False

    # Check PRD file exists
    spec_dir = file_path.parent
    prd_path = spec_dir / tasks_file.prd
    if not prd_path.exists():
        print(f"Error: PRD file not found: {prd_path}")
        return False

    # Summary
    print(f"PRD: {tasks_file.prd}")
    print(f"PRD file: {prd_path} (exists)")
    print(f"Branch: {tasks_file.branchName}")
    print(f"Tasks: {len(tasks_file.tasks)}")
    print()

    for task in tasks_file.tasks:
        status = "PASS" if task.passes else "PENDING"
        print(f"  [{status}] {task.id}: {task.title}")
        print(f"           Criteria: {len(task.acceptanceCriteria)}")

    print()
    print("Validation passed!")
    return True


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <path-to-tasks.json>")
        sys.exit(1)

    file_path = Path(sys.argv[1])
    success = verify_tasks(file_path)
    sys.exit(0 if success else 1)
