# Justfile for persuade - see https://github.com/casey/just

# Show available commands
default:
    @just --list

# --------------------------------------------------------------------------
# Development Setup
# --------------------------------------------------------------------------

# Complete development setup (all extras + git hooks)
setup:
    uv sync --all-extras
    uv run lefthook install
    @echo "Setup complete"

# --------------------------------------------------------------------------
# Quality Checks
# --------------------------------------------------------------------------

# Run all quality checks (lint + test)
check: lint test
    @echo "All checks passed"

# Run linter, formatter check, and type checker
lint:
    uvx ruff check .
    uvx ruff format --check .
    uvx ty check persuade/

# Auto-format code
format:
    uvx ruff format .
    uvx ruff check --fix .

# --------------------------------------------------------------------------
# Testing
# --------------------------------------------------------------------------

# Run all tests (accepts extra pytest args)
test *ARGS:
    uv run pytest tests/ -v {{ARGS}}

# Run tests with coverage report
test-cov:
    uv run pytest tests/ --cov=persuade --cov-report=term-missing --cov-report=html

# --------------------------------------------------------------------------
# Building & Publishing
# --------------------------------------------------------------------------

# Build package (sdist and wheel)
build: clean
    uvx --from build pyproject-build
    @echo "Built dist/"
    @ls -la dist/

# Check package before upload
check-dist: build
    uvx twine check dist/*

# Upload to Test PyPI
publish-test: check-dist
    uvx twine upload --repository testpypi dist/*
    @echo "Uploaded to Test PyPI"
    @echo "https://test.pypi.org/project/persuade/"

# Upload to PyPI (production)
publish: check-dist
    @echo "Publishing to PyPI (production)"
    @read -p "Continue? [y/N] " confirm && [ "$$confirm" = "y" ]
    uvx twine upload dist/*
    @echo "Uploaded to PyPI"
    @echo "https://pypi.org/project/persuade/"

# --------------------------------------------------------------------------
# Release (full workflow)
# --------------------------------------------------------------------------

# Full release: tag, GitHub release, PyPI upload
release: check
    #!/usr/bin/env bash
    set -euo pipefail

    VERSION=$(grep '^version = ' pyproject.toml | head -1 | cut -d'"' -f2)
    TAG="v${VERSION}"

    echo "Releasing ${TAG}"
    echo ""

    # ----------------------------
    # Pre-flight checks
    # ----------------------------

    # Check required tools
    for cmd in gh uv git; do
        if ! command -v "$cmd" &>/dev/null; then
            echo "Required command not found: $cmd"
            exit 1
        fi
    done

    # Check version format (semver)
    if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then
        echo "Invalid version format: ${VERSION} (expected X.Y.Z)"
        exit 1
    fi

    # Check for uncommitted changes
    if ! git diff --quiet HEAD; then
        echo "Uncommitted changes. Commit or stash first."
        exit 1
    fi

    # Check for untracked files in persuade/
    if [ -n "$(git ls-files --others --exclude-standard persuade/)" ]; then
        echo "Untracked files in persuade/. Add or ignore them first."
        git ls-files --others --exclude-standard persuade/
        exit 1
    fi

    # Check we're on main
    BRANCH=$(git branch --show-current)
    if [ "$BRANCH" != "main" ]; then
        echo "Must be on main branch (currently on ${BRANCH})"
        exit 1
    fi

    # Check we're up to date with origin
    git fetch origin main --quiet
    LOCAL=$(git rev-parse HEAD)
    REMOTE=$(git rev-parse origin/main)
    if [ "$LOCAL" != "$REMOTE" ]; then
        echo "Local main differs from origin/main. Pull or push first."
        echo "  Local:  $LOCAL"
        echo "  Remote: $REMOTE"
        exit 1
    fi

    # Check tag doesn't exist locally or remotely
    if git rev-parse "$TAG" >/dev/null 2>&1; then
        echo "Tag ${TAG} already exists locally"
        exit 1
    fi
    if git ls-remote --tags origin | grep -q "refs/tags/${TAG}$"; then
        echo "Tag ${TAG} already exists on origin"
        exit 1
    fi

    # Check CHANGELOG has entry for this version
    if ! grep -q "## \[${VERSION}\]" CHANGELOG.md; then
        echo "CHANGELOG.md missing entry for version ${VERSION}"
        echo "  Add a section: ## [${VERSION}] - $(date +%Y-%m-%d)"
        exit 1
    fi

    # Check version not already on PyPI
    if curl -s "https://pypi.org/pypi/persuade/${VERSION}/json" | grep -q '"version"'; then
        echo "Version ${VERSION} already exists on PyPI"
        exit 1
    fi

    # ----------------------------
    # Confirmation
    # ----------------------------

    echo "All pre-flight checks passed"
    echo ""
    echo "This will:"
    echo "  1. Create git tag ${TAG}"
    echo "  2. Push tag to origin"
    echo "  3. Create GitHub release"
    echo "  4. Build and upload to PyPI"
    echo ""
    read -p "Continue? [y/N] " confirm
    if [ "$confirm" != "y" ]; then
        echo "Aborted."
        exit 1
    fi

    # ----------------------------
    # Release
    # ----------------------------

    # Create and push tag
    git tag -a "$TAG" -m "Release ${TAG}"
    git push origin "$TAG" --no-verify
    echo "Tag ${TAG} pushed"

    # Create GitHub release
    gh release create "$TAG" --title "${TAG}" --generate-notes
    echo "GitHub release created"

    # Build and upload to PyPI
    just clean
    uvx --from build pyproject-build
    uvx twine check dist/*
    uvx twine upload dist/*

    echo ""
    echo "Released ${TAG}"
    echo "https://github.com/stavxyz/persuade/releases/tag/${TAG}"
    echo "https://pypi.org/project/persuade/${VERSION}/"

# --------------------------------------------------------------------------
# Version Bump
# --------------------------------------------------------------------------

# Bump version, sync lockfile, commit, and open a PR
bump VERSION:
    #!/usr/bin/env bash
    set -euo pipefail

    NEW="{{VERSION}}"

    # Validate semver format
    if ! echo "$NEW" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
        echo "Invalid version: ${NEW} (expected X.Y.Z)"
        exit 1
    fi

    OLD=$(grep '^version = ' pyproject.toml | head -1 | cut -d'"' -f2)
    if [ "$OLD" = "$NEW" ]; then
        echo "Already at version ${NEW}"
        exit 1
    fi

    echo "Bumping ${OLD} -> ${NEW}"

    # Update pyproject.toml (cross-platform: perl instead of sed)
    perl -i -pe "s/^version = \"${OLD}\"/version = \"${NEW}\"/" pyproject.toml

    # Update __init__.py
    perl -i -pe "s/__version__ = \"${OLD}\"/__version__ = \"${NEW}\"/" persuade/__init__.py

    # Update CHANGELOG: rename [Unreleased] to [X.Y.Z] with today's date
    DATE=$(date +%Y-%m-%d)
    if grep -q '## \[Unreleased\]' CHANGELOG.md; then
        perl -i -pe "s/## \\[Unreleased\\]/## [${NEW}] - ${DATE}/" CHANGELOG.md
        # Insert new [Unreleased] section above the new version
        perl -i -pe "s/^(## \\[${NEW}\\])/## [Unreleased]\\n\\n\$1/" CHANGELOG.md
        echo "CHANGELOG.md: [Unreleased] -> [${NEW}] - ${DATE}"
    else
        echo "CHANGELOG.md has no [Unreleased] section."
        echo "  Add your changes under '## [Unreleased]' before bumping."
        # Revert changes before exiting
        git checkout -- pyproject.toml persuade/__init__.py
        exit 1
    fi

    # Update lockfile
    uv lock --quiet
    echo "Updated pyproject.toml, __init__.py, CHANGELOG.md, uv.lock"

    # Create branch, commit, and PR
    BRANCH="chore/bump-v${NEW}"
    git checkout -b "$BRANCH"
    git add pyproject.toml persuade/__init__.py uv.lock CHANGELOG.md
    git commit -m "chore: bump version to ${NEW}"
    git push -u origin "$BRANCH"
    gh pr create --title "chore: bump version to ${NEW}" --body "Bump version ${OLD} -> ${NEW} (pyproject.toml, __init__.py, CHANGELOG.md, uv.lock)"

    echo ""
    echo "PR created for v${NEW}"

# --------------------------------------------------------------------------
# Utilities
# --------------------------------------------------------------------------

# Clean build artifacts
clean:
    rm -rf .mypy_cache .pytest_cache .ruff_cache .coverage htmlcov/
    rm -rf dist/ build/ *.egg-info
    find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
    @echo "Cleaned"

# Show current version
version:
    @uv run python -c "import persuade; print(persuade.__version__)"

# Run the CLI
cli *ARGS:
    uv run persuade {{ARGS}}
