.PHONY: all setup setup-ci setup-quality setup-molecule setup-release install update lint ansible-lint makefile-lint lint-all test test-unit pytest-cov molecule molecule-all test-all clean workflow-lint workflow-dryrun workflow-check install-tools
.PHONY: configure-gitea-pypi
.PHONY: create-task create-pr push-with-pr git-push

PYTHON := python3
VENV := .venv
BIN := $(VENV)/bin
CHECKMAKE := $(shell command -v checkmake 2>/dev/null || echo $(HOME)/go/bin/checkmake)

all: setup

# Helper: run pip install with Gitea registry configured
# Usage: $(PIP_INSTALL) install -e '.[ci,lint]'
PIP_INSTALL := if [ -z "$$REPO_TOKEN" ]; then . ./.env 2>/dev/null; fi; \
	REPO_TOKEN="$${REPO_TOKEN:-$$GITEA_REGISTRY_TOKEN}"; \
	if [ -n "$$REPO_TOKEN" ]; then export PIP_EXTRA_INDEX_URL="https://emil:$$REPO_TOKEN@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"; fi; \
	$(BIN)/pip

# Configure Gitea private PyPI registry so pip can find devx and other
# private packages. In CI, REPO_TOKEN is set as a secret. Locally, it's in .env.
configure-gitea-pypi:
	@if [ -z "$$REPO_TOKEN" ]; then . ./.env 2>/dev/null; fi; \
	REPO_TOKEN="$${REPO_TOKEN:-$$GITEA_REGISTRY_TOKEN}"; \
	if [ -z "$$REPO_TOKEN" ]; then echo "[configure-gitea-pypi] REPO_TOKEN not set — skipping (devx must be on public PyPI)"; exit 0; fi; \
	echo "[configure-gitea-pypi] Gitea PyPI registry configured (REPO_TOKEN present)."

# Full setup for local development (all deps, tools, collections, hooks)
# devx is installed via pip install -e .[dev] (devx is in dev extra)
setup: $(VENV)/bin/activate .env activate-scripts configure-gitea-pypi
	@$(PIP_INSTALL) install -e '.[dev]'
	@$(BIN)/python -m devx.tools.install_checkmake
	@$(BIN)/python -m devx.tools.install_tools
	@export PATH="$(HOME)/.local/bin:$$PATH"; \
	$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install

# Lean setup for CI jobs that need pytest + lint tools + runtime deps
# (detect-changes, discover-runners, pr-review, sync-wiki, badges)
# badges job runs generate_badges.py which needs ruff, pyright, bandit
setup-ci: $(VENV)/bin/activate .env configure-gitea-pypi
	@$(PIP_INSTALL) install -e '.[ci,lint]'
	@$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-ansible-collections --no-pre-commit --no-tea-login

# Setup for the quality job (lint + test deps, actionlint tool)
setup-quality: $(VENV)/bin/activate .env configure-gitea-pypi
	@$(PIP_INSTALL) install -e '.[ci,lint]'
	@$(BIN)/python -m devx.tools.install_tools
	@export PATH="$(HOME)/.local/bin:$$PATH"; \
	$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-ansible-collections --no-pre-commit --no-tea-login

# Full setup for molecule testing (needs ansible, molecule, collections)
setup-molecule: $(VENV)/bin/activate .env configure-gitea-pypi
	@$(PIP_INSTALL) install -e '.[ci,molecule]'
	@$(BIN)/python -m devx.tools.install_tools
	@export PATH="$(HOME)/.local/bin:$$PATH"; \
	$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-pre-commit --no-tea-login

# Setup for release jobs (needs git-cliff, tea, and lint tools for release.py)
setup-release: $(VENV)/bin/activate .env configure-gitea-pypi
	@$(PIP_INSTALL) install -e '.[ci,lint]'
	@$(BIN)/python -m devx.tools.install_tools --tool git-cliff --tool tea
	@export PATH="$(HOME)/.local/bin:$$PATH"; \
	$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-ansible-collections --no-pre-commit

.env:
	@if [ ! -f .env ]; then \
		cp .env.example .env; \
		echo "Created .env from .env.example — please edit it with your credentials."; \
	fi

$(VENV)/bin/activate:
	@python3 -c "import sys; v=sys.version_info; assert v >= (3, 12), f'Python 3.12+ required, found {v.major}.{v.minor}'; print(f'Python {v.major}.{v.minor}.{v.micro} OK')"
	$(PYTHON) -m venv $(VENV)
	$(BIN)/pip install --upgrade pip setuptools wheel

activate-scripts: $(VENV)/bin/activate
	@test -f activate.sh || (echo '#!/usr/bin/env bash' > activate.sh && echo 'source "$$(cd "$$(dirname "$${BASH_SOURCE[0]}")" && pwd)/.venv/bin/activate"' >> activate.sh && chmod +x activate.sh)
	@test -f activate.fish || (echo '#!/usr/bin/env fish' > activate.fish && echo 'set -l script_dir (dirname (status --current-filename))' >> activate.fish && echo 'source "$$script_dir/.venv/bin/activate.fish"' >> activate.fish && chmod +x activate.fish)
	@test -f activate.zsh || (echo '#!/usr/bin/env zsh' > activate.zsh && echo '0="$${ZERO:-$${0:#$$ZSH_ARGZERO}}"' >> activate.zsh && echo '0="$${$${(M)0:#/*}:-$$PWD/$$0}"' >> activate.zsh && echo 'source "$${0:A:h}/.venv/bin/activate"' >> activate.zsh && chmod +x activate.zsh)

install-hooks:
	@git config core.hooksPath hooks
	@chmod +x hooks/pre-commit hooks/pre-push 2>/dev/null || true
	@echo "core.hooksPath set to hooks/ — tracked hooks are now live."

checkmake:
	@$(BIN)/python -m devx.tools.install_checkmake

install-tools:
	@$(BIN)/python -m devx.tools.install_tools

install:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make install HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm install $(HOST) $(if $(USER),--user $(USER),) $(if $(KEY),--key $(KEY),) $(if $(NAME),--name $(NAME),) $(if $(TOKEN),--token $(TOKEN),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

update:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make update HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm update $(HOST) $(if $(USER),--user $(USER),) $(if $(KEY),--key $(KEY),) $(if $(VERSION),--version $(VERSION),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

start:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make start HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm start $(NAME) $(if $(HOST),--host $(HOST),) $(if $(USER),--user $(USER),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

stop:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make stop HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm stop $(NAME) $(if $(HOST),--host $(HOST),) $(if $(USER),--user $(USER),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

enable:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make enable HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm enable $(NAME) $(if $(HOST),--host $(HOST),) $(if $(USER),--user $(USER),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

disable:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make disable HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm disable $(NAME) $(if $(HOST),--host $(HOST),) $(if $(USER),--user $(USER),) $(if $(TOKEN),--token $(TOKEN),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

status:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make status HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm status $(NAME) $(if $(HOST),--host $(HOST),) $(if $(USER),--user $(USER),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

remove:
	@if [ -z "$(HOST)" ]; then echo "HOST is required. Example: make remove HOST=192.168.1.10"; exit 1; fi
	$(BIN)/grm remove $(NAME) $(if $(HOST),--host $(HOST),) $(if $(USER),--user $(USER),) $(if $(TOKEN),--token $(TOKEN),) $(if $(ASK_BECOME_PASS),--ask-become-pass,)

lint-ruff:
	$(BIN)/ruff check src/ tests/

lint-format:
	$(BIN)/ruff format --check src/ tests/

typecheck:
	$(BIN)/pyright

lint: lint-ruff lint-format typecheck lint-bandit

lint-bandit:
	$(BIN)/bandit -r src/

lint-deps:
	@echo "Checking dependencies for known vulnerabilities..."
	@.venv/bin/python -m ensurepip 2>/dev/null || true
	@PIPAPI_PYTHON_LOCATION=$$(pwd)/.venv/bin/python \
		.venv/bin/pip-audit --desc --skip-editable 2>&1 || true

ansible-lint:
	PATH="$(PWD)/$(BIN):$$PATH" $(BIN)/ansible-lint ansible/

makefile-lint:
	@if command -v $(CHECKMAKE) >/dev/null 2>&1 || [ -x "$(CHECKMAKE)" ]; then \
		$(CHECKMAKE) Makefile; \
	else \
		echo "checkmake not found, skipping Makefile lint"; \
	fi

lint-all: lint ansible-lint makefile-lint workflow-lint

workflow-lint:
	@command -v actionlint >/dev/null 2>&1 || { \
		echo "actionlint not found. Install: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)"; \
		exit 1; \
	}
	actionlint -config-file .gitea/actionlint.yaml .gitea/workflows/*.yml

workflow-dryrun:
	@command -v act_runner >/dev/null 2>&1 || { echo "act_runner not found. Install: https://gitea.com/gitea/act_runner/releases"; exit 1; }
	@echo "Dry-running all workflows (no Docker containers started)..."
	act_runner exec --dryrun -W .gitea/workflows/ 2>&1 | grep -E 'DRYRUN|ERROR|FAIL|Job'

workflow-check: workflow-lint workflow-dryrun
	@echo "Workflow checks passed (static lint + dry-run)."

test-unit:
	$(BIN)/pytest tests/unit/ -v --no-cov

test-integration:
	$(BIN)/pytest tests/integration/ -v --no-cov

pytest-cov:
	$(BIN)/pytest tests/ -v --cov=src/gitea_runner_manager --cov-report=term-missing --cov-fail-under=100

MOLECULE := $(realpath $(BIN))/molecule
MOLECULE_BASE := cd $(CURDIR)/ansible/roles/gitea-runner && ANSIBLE_ALLOW_BROKEN_CONDITIONALS=true ANSIBLE_INJECT_INVOCATION=1 $(MOLECULE)

# Quick local test: Ubuntu 22.04 only, all scenarios
molecule:
	@set -e; for s in default multi-instance lifecycle template-content deregister update; do if [ "$$s" = "default" ]; then $(MOLECULE_BASE) test; else $(MOLECULE_BASE) test -s $$s; fi; done

# All scenarios on all supported platforms (sequential; use CI matrix for parallel execution)
molecule-all:
	@$(BIN)/python -m devx.molecule.molecule_all --bin "$(BIN)"

test: test-all

test-all: pytest-cov molecule

clean:
	find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
	find . -type f -name "*.pyc" -delete 2>/dev/null || true
	rm -rf .coverage htmlcov/ .molecule/

# --- Vikunja task and PR management (via devx.mak fragment) -------------------
# Project config (task prefix, Vikunja project ID, repo owner/name) is read
# from [tool.devx] in pyproject.toml by devx.config — no Makefile variables needed.
DEVX_PYTHON := $(BIN)/python

# Include shared targets from devx package (create-task, create-pr, push-with-pr, check-config)
# Silent if devx not installed yet — run 'make setup' first.
DEVX_MAK := $(shell $(BIN)/python -c \
	"from pathlib import Path; import devx; print(Path(devx.__file__).parent / 'make' / 'devx.mak')" \
	2>/dev/null)
-include $(DEVX_MAK)

# Aliases for project-specific target names
create-task: devx-create-task
create-pr: devx-create-pr
push-with-pr: devx-push-with-pr
git-push: devx-push
