# Unraid MCP Server — Justfile
# Run `just` to list available recipes

default:
    @just --list

# ── Development ───────────────────────────────────────────────────────────────

# Start development server (hot-reload via watchfiles)
dev:
    uv run python -m unraid_mcp

# Run tests
test:
    uv run pytest tests/ -v

# Run linter (ruff)
lint:
    uv run ruff check .

# Format code (ruff)
fmt:
    uv run ruff format .

# Type-check (ty)
typecheck:
    uv run ty check unraid_mcp/

# Validate skills SKILL.md files exist and are non-empty
validate-skills:
    @echo "=== Validating skills ==="
    @for f in plugins/unraid/skills/*/SKILL.md; do \
        if [ -f "$$f" ]; then \
            echo "  ✓ $$f"; \
        else \
            echo "  ✗ SKILL.md not found in plugins/unraid/skills/"; \
            exit 1; \
        fi; \
    done
    @echo "Skills validation passed"

# Validate the Claude Code marketplace + plugin manifest structure
validate-marketplace:
    bash scripts/validate-marketplace.sh

# Build Docker image
build:
    docker build -t unraid-mcp .

# ── Docker Compose ────────────────────────────────────────────────────────────

# Start containers
up:
    docker compose up -d

# Stop containers
down:
    docker compose down

# Restart containers
restart:
    docker compose restart

# Tail container logs
logs:
    docker compose logs -f

# Check /health endpoint
health:
    @PORT=$$(grep -E '^UNRAID_MCP_PORT=' .env 2>/dev/null | cut -d= -f2 || echo 6970); \
    curl -sf "http://localhost:$$PORT/health" | python3 -m json.tool || echo "Health check failed"

# ── Live Testing ──────────────────────────────────────────────────────────────

# Run live integration tests against a running server
test-live:
    uv run pytest tests/ -v -m live

# Run HTTP end-to-end smoke-test against the local server (auto-reads token from ~/.unraid-mcp/.env)
test-http:
    bash tests/mcporter/test-http.sh

# Run HTTP e2e test with auth disabled (for gateway-protected deployments)
test-http-no-auth:
    bash tests/mcporter/test-http.sh --skip-auth

# Run HTTP e2e test against a remote URL
# Usage: just test-http-remote https://unraid.tootie.tv/mcp
test-http-remote url:
    bash tests/mcporter/test-http.sh --url {{url}} --skip-auth

# ── Setup ─────────────────────────────────────────────────────────────────────

# Create .env from .env.example if missing
setup:
    @if [ ! -f .env ]; then \
        cp .env.example .env && chmod 600 .env; \
        echo "Created .env from .env.example — fill in your credentials"; \
    else \
        echo ".env already exists"; \
    fi

# Generate a secure bearer token for UNRAID_MCP_TOKEN
gen-token:
    @python3 -c "import secrets; print(secrets.token_urlsafe(32))"

# ── Quality Gates ─────────────────────────────────────────────────────────────

# Run repo contract checks (version sync, env hygiene, marketplace structure)
check-contract:
    bash scripts/check-version-sync.sh
    bash scripts/block-env-commits.sh
    bash scripts/validate-marketplace.sh

# ── CLI Generation ────────────────────────────────────────────────────────────

# Generate a standalone CLI for this server (requires running server)
generate-cli:
    #!/usr/bin/env bash
    set -euo pipefail
    PORT="${UNRAID_MCP_PORT:-6970}"
    echo "⚠  Server must be running on port ${PORT} (run 'just dev' first)"
    echo "⚠  Generated CLI embeds your OAuth token — do not commit or share"
    mkdir -p dist dist/.cache
    current_hash=$(timeout 10 curl -sf \
      -H "Authorization: Bearer $MCP_TOKEN" \
      -H "Accept: application/json, text/event-stream" \
      "http://localhost:${PORT}/mcp/tools/list" 2>/dev/null | sha256sum | cut -d' ' -f1 || echo "nohash")
    cache_file="dist/.cache/unraid-mcp-cli.schema_hash"
    if [[ -f "$cache_file" ]] && [[ "$(cat "$cache_file")" == "$current_hash" ]] && [[ -f "dist/unraid-mcp-cli" ]]; then
      echo "SKIP: unraid-mcp tool schema unchanged — use existing dist/unraid-mcp-cli"
      exit 0
    fi
    timeout 30 mcporter generate-cli \
      --command "http://localhost:${PORT}/mcp" \
      --header "Authorization: Bearer $MCP_TOKEN" \
      --name unraid-mcp-cli \
      --output dist/unraid-mcp-cli
    printf '%s' "$current_hash" > "$cache_file"
    echo "✓ Generated dist/unraid-mcp-cli (requires bun at runtime)"

# ── Cleanup ───────────────────────────────────────────────────────────────────

# Remove build artifacts, caches, and compiled files
clean:
    rm -rf dist/ build/ .pytest_cache/ .ruff_cache/ .mypy_cache/ htmlcov/ .coverage coverage.xml
    find . -type d -name __pycache__ -not -path './.venv/*' -exec rm -rf {} + 2>/dev/null || true
    find . -name '*.pyc' -not -path './.venv/*' -delete 2>/dev/null || true
    @echo "Cleaned build artifacts"

# Releases are automated via release-please — DO NOT bump versions by hand.
# Write Conventional Commits (feat: / fix: / feat!:) and merge to main;
# release-please opens a release PR that bumps the version across pyproject.toml
# and the plugin manifests, updates CHANGELOG.md, then tags + publishes on merge.
publish:
    @echo "Releases are automated via release-please (.github/workflows/release-please.yml)."
    @echo ""
    @echo "  1. Land changes on main using Conventional Commit messages:"
    @echo "       fix: ...  -> patch     feat: ...  -> minor     feat!: ...  -> major"
    @echo "  2. release-please opens/updates a 'chore(main): release X.Y.Z' PR."
    @echo "  3. Merge that PR -- it tags vX.Y.Z and triggers publish-pypi + docker-publish."
    @echo ""
    @echo "Version is read at runtime from package metadata; never edit version strings by hand."

