#!/usr/bin/env python3
"""Project contract: single source of truth for project types, stacks,
expected structure, frontend markers.

Imported by both ``spec-status.py`` and ``project-status.py`` via
``importlib.util.spec_from_file_location`` (no ``sys.path`` mutation).
Stdlib-only imports.

Contract symbols:
    ProjectType              — StrEnum with 7 members (incl. MCP_SERVER + UNKNOWN)
    VALID_TYPES              — set[str] excluding "unknown"
    STACK_REQUIRED           — dict[type -> list[str]] of mandatory stack items
    STRUCTURE_EXPECTED       — dict[type -> list[str]] of expected top-level dirs/files
    FRONTEND_STACK_MARKERS   — dict with keys for fullstack frontend detection
"""

from __future__ import annotations

from enum import StrEnum


class ProjectType(StrEnum):
    """Project type enum (auto-detected or spec-declared)."""

    FULLSTACK = "fullstack"
    BACKEND = "backend"
    CLI = "cli"
    BOT = "bot"
    WORKER = "worker"
    MCP_SERVER = "mcp-server"
    UNKNOWN = "unknown"


# Excludes "unknown" — used by spec-status PROJECT_TYPE phase validation.
VALID_TYPES: set[str] = {t.value for t in ProjectType if t != ProjectType.UNKNOWN}

# Mandatory stack items per project type (spec-status Phase 2 STACK).
# `uv` stays in ALL stacks (build-tool, mentioned in stack.md).
STACK_REQUIRED: dict[str, list[str]] = {
    "backend": ["fastapi", "tortoise", "uv", "pytest", "ruff", "mypy", "loguru", "pydantic"],
    "fullstack": [
        "fastapi",
        "tortoise",
        "svelte",
        "sveltekit",
        "biome",
        "uv",
        "ruff",
        "mypy",
        "pytest",
        "tailwind",
        "shadcn",
        "typescript",
    ],
    "mcp-server": ["fastapi", "mcp", "patchright", "uv"],
    "cli": ["typer", "uv", "hatchling", "ruff", "mypy", "pytest"],
    "bot": ["aiogram", "fastapi", "uv", "ruff", "mypy", "pytest"],
    "worker": ["prefect", "uv", "ruff", "mypy", "pytest"],
}

# Expected top-level structure per type (project-status check_structure).
# BACKEND is resolved dynamically by ``_expected_backend_paths`` (src/<pkg>/...),
# so it is NOT in this dict. mcp-server structure is TBD out of scope.
# Keys are strings (project type values), NOT ProjectType enum members —
# kept as plain strings for portability across both oracles.
STRUCTURE_EXPECTED: dict[str, list[str]] = {
    "fullstack": ["backend", "frontend"],
    "cli": ["src"],  # src/<package>/ — checked generically
    "bot": ["src/bot.py"],
    "worker": ["src/flow.py"],
    "unknown": [],
}

# Fullstack frontend stack markers (project-status _check_type_specific_structure).
# `tailwindcss` + `bits-ui` (shadcn-svelte proxy) in package.json deps, plus
# `components.json` (shadcn config) and `tsconfig.json` (TypeScript) existence.
FRONTEND_STACK_MARKERS: dict[str, list[str]] = {
    "fullstack_package_deps": ["tailwindcss", "bits-ui"],
    "fullstack_files": ["frontend/components.json", "frontend/tsconfig.json"],
}

# Fullstack mobile-first markers (project-status _check_mobile_first, issue #278).
# Distinct from FRONTEND_STACK_MARKERS so the stack check stays focused on the
# Tailwind/shadcn/TS trio. Keys:
#   fullstack_files          — paths (relative to repo root) that must exist
#                              for PWA + mobile Playwright + a11y to be present.
#   fullstack_app_html_markers — substrings that must appear in app.html <head>.
MOBILE_FIRST_MARKERS: dict[str, list[str]] = {
    "fullstack_files": [
        "frontend/static/manifest.webmanifest",
        "frontend/tests/e2e/mobile.spec.ts",
        "frontend/tests/e2e/accessibility.spec.ts",
    ],
    "fullstack_app_html_markers": ["viewport", "manifest"],
}
