SHELL := /bin/bash

# --- Configuration ---
IMAGE_NAME := audio-engine-hub
TAG := latest
REGISTRY := git.wlkns.org
USERNAME := stephan
# Default internal application port
PORT := 8000

# --- Port Checking Functions ---

# Function to check if required Traefik ports are free
# Exits if any are busy, does not suggest alternatives.
define check_traefik_ports_free
check_traefik_ports_free_func() { \
    echo "Checking if Traefik ports ($(TRAEFIK_WEB_PORT), $(TRAEFIK_DASHBOARD_PORT)) are free..." >&2; \
    local busy_ports=""; \
    if ss -tulnp | grep ":$(TRAEFIK_WEB_PORT) " > /dev/null; then \
        busy_ports="$$busy_ports $(TRAEFIK_WEB_PORT)"; \
    fi; \
    if ss -tulnp | grep ":$(TRAEFIK_DASHBOARD_PORT) " > /dev/null; then \
        busy_ports="$$busy_ports $(TRAEFIK_DASHBOARD_PORT)"; \
    fi; \
    if [ -n "$$busy_ports" ]; then \
        echo "ERROR: The following Traefik ports are already in use: $$busy_ports. Please free them or stop Traefik if already running." >&2; \
        exit 1; \
    fi; \
    echo "Traefik ports are free." >&2; \
} ; \
check_traefik_ports_free_func
endef

# --- Docker Commands ---

.PHONY: build
build:
	@echo "Building Docker image: $(IMAGE_NAME):$(TAG)"
	docker build --no-cache -t $(IMAGE_NAME):$(TAG) .

.PHONY: run
run:
	@APP_PORT=$$(bash -c 'port=$${PORT:-8000}; while ss -tulnp | grep -q :$$port; do echo "Port $$port is busy. Checking next..." >&2; ((port++)); done; echo $$port'); \
	echo "Using host port $$APP_PORT for single app container" && \
	docker run -d -p $$APP_PORT:$(PORT) --name $(IMAGE_NAME) $(IMAGE_NAME):$(TAG)

.PHONY: stop
stop:
	@echo "Stopping Docker containers..."
	docker compose stop || true
	docker compose rm -f || true
	docker stop $(IMAGE_NAME) || true
	docker rm $(IMAGE_NAME) || true

.PHONY: logs
logs:
	@echo "Showing logs for container: $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app)"
	docker logs -f $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app)

.PHONY: shell
shell:
	@echo "Accessing shell in container: $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app)"
	docker exec -it $(if $(CONTAINER),$(CONTAINER),$(IMAGE_NAME)_app) /bin/bash

# --- Docker Compose Commands ---

.PHONY: up
up:
	@echo "Starting development environment by pulling image from registry..."
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=$(TAG) && \
	docker compose up -d

.PHONY: dev-up
dev-up:
	@APP_PORT=$$(bash -c 'port=$${PORT:-8000}; while ss -tulnp | grep -q :$$port; do echo "Port $$port is busy. Checking next..." >&2; ((port++)); done; echo $$port'); \
	echo "Starting development environment (local build) on port $$APP_PORT..."; \
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=$(TAG) && \
	APP_PORT=$$APP_PORT docker compose up --build -d

.PHONY: down
down:
	@echo "Stopping development environment with Docker Compose..."
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=$(TAG) && \
	docker compose down

# --- Test Environment Commands ---

.PHONY: kokoro-up
kokoro-up:
	@echo "Starting Kokoro test environment on port 8001..."
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=dev-kokoro-v5 && \
	docker compose -f docker-compose.kokoro-test.yml up -d

.PHONY: kokoro-down
kokoro-down:
	@echo "Stopping Kokoro test environment..."
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=dev-kokoro-v5 && \
	docker compose -f docker-compose.kokoro-test.yml down

.PHONY: kokoro-logs
kokoro-logs:
	@echo "Showing logs for Kokoro test container..."
	docker logs -f audio-engine-hub_kokoro_test

.PHONY: xtts-up
xtts-up:
	@echo "Starting XTTS test environment on port 8002..."
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=dev-xtts && \
	docker compose -f docker-compose.xtts-test.yml up -d

.PHONY: xtts-down
xtts-down:
	@echo "Stopping XTTS test environment..."
	export IMAGE_NAME=$(IMAGE_NAME) && \
	export REGISTRY=$(REGISTRY) && \
	export USERNAME=$(USERNAME) && \
	export TAG=dev-xtts && \
	docker compose -f docker-compose.xtts-test.yml down

.PHONY: xtts-logs
xtts-logs:
	@echo "Showing logs for XTTS test container..."
	docker logs -f audio-engine-hub_xtts_test

# --- Image Management ---

.PHONY: pull
pull:
	@echo "Pulling image $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) from registry..."
	docker pull $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)

.PHONY: tag
tag:
	@echo "Tagging image $(IMAGE_NAME):$(TAG) as $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)"
	docker tag $(IMAGE_NAME):$(TAG) $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)

.PHONY: push
push: build tag
	@echo "Pushing image $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG) to registry..."
	docker push $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):$(TAG)

# --- Tagged Image Management ---

.PHONY: build-kokoro
build-kokoro:
	@echo "Building Kokoro test image: $(IMAGE_NAME):dev-kokoro-v5"
	docker build --no-cache -t $(IMAGE_NAME):dev-kokoro-v5 .
	docker tag $(IMAGE_NAME):dev-kokoro-v5 $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):dev-kokoro-v5

.PHONY: push-kokoro
push-kokoro: build-kokoro
	@echo "Pushing Kokoro test image to registry..."
	docker push $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):dev-kokoro-v5

.PHONY: pull-kokoro
pull-kokoro:
	@echo "Pulling Kokoro test image from registry..."
	docker pull $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):dev-kokoro-v5

.PHONY: build-xtts
build-xtts:
	@echo "Building XTTS test image: $(IMAGE_NAME):dev-xtts"
	docker build --no-cache -t $(IMAGE_NAME):dev-xtts .
	docker tag $(IMAGE_NAME):dev-xtts $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):dev-xtts

.PHONY: push-xtts
push-xtts: build-xtts
	@echo "Pushing XTTS test image to registry..."
	docker push $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):dev-xtts

.PHONY: pull-xtts
pull-xtts:
	@echo "Pulling XTTS test image from registry..."
	docker pull $(REGISTRY)/$(USERNAME)/$(IMAGE_NAME):dev-xtts

.PHONY: test
test:
	@if [ -d ".venv" ]; then \
		echo "Activating virtual environment..."; \
		. .venv/bin/activate; \
	fi; \
	export PYTHONPATH=$(PWD); \
	echo "Running tests with coverage..." && \
	pytest --cov=. app/ tests/

.PHONY: health-check
health-check:
	@echo "Running health check on running container..."
	@CONTAINER_ID=$$(docker compose ps -q app); \
	if [ -z "$$CONTAINER_ID" ]; then \
	    echo "ERROR: App container is not running. Please run 'make up' first." >&2; \
	    exit 1; \
	fi; \
	HOST_PORT=$$(docker port $$CONTAINER_ID 8000 | cut -d: -f2); \
	if [ -z "$$HOST_PORT" ]; then \
	    echo "ERROR: Could not determine host port for the app container." >&2; \
	    exit 1; \
	fi; \
	echo "App container is running on port $$HOST_PORT."; \
	echo "Waiting for app to initialize..."; \
	sleep 2; \
	curl -s http://localhost:$$HOST_PORT/health | ./scripts/health_check.py

# --- Cleanup ---

.PHONY: clean
clean:
	@echo "Cleaning up stopped containers and dangling images..."
	docker container prune -f
	docker image prune -f

.PHONY: help
help:
	@echo "Available commands:"
	@echo ""
	@echo "Main Deployment:"
	@echo "  build        - Build the Docker image"
	@echo "  run          - Run the Docker container (single app, no Traefik)"
	@echo "  stop         - Stop and remove the Docker container"
	@echo "  logs         - Follow the logs of the container"
	@echo "  shell        - Get a shell inside the running container"
	@echo "  up           - Start the dev environment by pulling image from registry"
	@echo "  dev-up       - Start the dev environment by building image locally"
	@echo "  down         - Stop the dev environment with docker-compose"
	@echo ""
	@echo "Test Environments:"
	@echo "  kokoro-up    - Start Kokoro test environment (port 8001)"
	@echo "  kokoro-down  - Stop Kokoro test environment"
	@echo "  kokoro-logs  - View Kokoro test container logs"
	@echo "  xtts-up      - Start XTTS test environment (port 8002)"
	@echo "  xtts-down    - Stop XTTS test environment"
	@echo "  xtts-logs    - View XTTS test container logs"
	@echo ""
	@echo "Image Management (main 'latest' tag):"
	@echo "  pull         - Pull the Docker image from the registry"
	@echo "  tag          - Tag the image for a registry"
	@echo "  push         - Push the image to a registry (after tagging)"
	@echo ""
	@echo "Image Management (test tags):"
	@echo "  build-kokoro - Build Kokoro test image (dev-kokoro-v5 tag)"
	@echo "  push-kokoro  - Build and push Kokoro test image to registry"
	@echo "  pull-kokoro  - Pull Kokoro test image from registry"
	@echo "  build-xtts   - Build XTTS test image (dev-xtts tag)"
	@echo "  push-xtts    - Build and push XTTS test image to registry"
	@echo "  pull-xtts    - Pull XTTS test image from registry"
	@echo ""
	@echo "Testing & Maintenance:"
	@echo "  test         - Run the pytest test suite"
	@echo "  health-check - Run a sanity check on the deployed container"
	@echo "  clean        - Clean up unused containers and images"
	@echo "  help         - Show this help message"

.DEFAULT_GOAL := help
