# Raccoon Mission: uncloseai-speech Development Makefile
# Deploy to remote server with ease
# Configuration is loaded from vars.sh (copy vars.sh.example to vars.sh)

# Load configuration from vars.sh if it exists
ifneq (,$(wildcard vars.sh))
    include vars.sh
    export
endif

# Fallback defaults if vars.sh is not found
REMOTE_HOST ?= localhost
REMOTE_USER ?= $(USER)
REMOTE_PATH ?= ~/uncloseai-speech
CONTAINER_NAME ?= uncloseai-speech-server-1

.PHONY: help deploy sync restart logs test clean stop start voices voices-qwen voices-piper voices-xtts voices-kokoro test-kokoro voices-silero test-silero voices-chatterbox test-chatterbox push-all hydrate load-test test-qwen venv venv-run local local-cpu

help:
	@echo "🦝 Raccoon TTS Mission - Development Commands"
	@echo ""
	@echo "Quick Start (Docker with GPU):"
	@echo "  make local       - Build and run locally with GPU support"
	@echo "  make local-cpu   - Build and run locally (CPU only, slower)"
	@echo "  make test        - Test Qwen3-TTS endpoint"
	@echo "  make logs        - Tail container logs"
	@echo ""
	@echo "Quick Start (No Docker):"
	@echo "  make venv        - Create Python virtual environment"
	@echo "  make venv-run    - Run server in virtual environment"
	@echo ""
	@echo "Remote Deployment:"
	@echo "  make deploy      - Full deploy: sync files, restart container"
	@echo "  make sync        - Sync local files to remote server"
	@echo "  make restart     - Restart the Docker container"
	@echo ""
	@echo "Testing:"
	@echo "  make test        - Test TTS endpoint (Qwen3-TTS)"
	@echo "  make test-qwen   - Test Qwen3-TTS voice cloning"
	@echo "  make hydrate     - Test all configured voices"
	@echo "  make load-test   - Concurrent load test"
	@echo ""
	@echo "Other Engines (disabled by default):"
	@echo "  make test-xtts     - Test XTTS HD endpoint"
	@echo "  make test-kokoro   - Test Kokoro fast TTS"
	@echo "  make test-silero   - Test Silero TTS endpoint"
	@echo "  make voices-piper  - Download Piper voices"
	@echo "  make voices-xtts   - Download XTTS voices"
	@echo "  make voices-kokoro - Download Kokoro models"
	@echo "  make voices-silero - Download Silero models"
	@echo ""
	@echo "Container Management:"
	@echo "  make start       - Start Docker container"
	@echo "  make stop        - Stop Docker container"
	@echo "  make clean       - Stop and remove container"
	@echo ""
	@echo "Git:"
	@echo "  make push-all    - Push to all git remotes"

sync:
	@echo "📦 Syncing files to $(REMOTE_HOST)..."
	rsync -avz --exclude '.git' --exclude '__pycache__' --exclude '*.pyc' \
		--exclude 'voices/*' --exclude 'config/voice_to_speaker.yaml' \
		./ $(REMOTE_USER)@$(REMOTE_HOST):$(REMOTE_PATH)/
	@echo "📝 Ensuring speech.env exists..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && [ -f speech.env ] || cp sample.env speech.env"

deploy: sync restart
	@echo "✅ Deployment complete!"

# ============================================================================
# Local Development (Docker)
# ============================================================================

local:
	@echo "🐳 Building and running with GPU support..."
	@[ -f speech.env ] || cp sample.env speech.env
	docker compose up -d --build
	@echo ""
	@echo "✅ Container started! Qwen3-TTS model will download on first request (~3.4GB)"
	@echo "   Test with: make test"
	@echo "   View logs: make logs"

local-cpu:
	@echo "🐳 Building and running (CPU only - slower inference)..."
	@[ -f speech.env ] || cp sample.env speech.env
	docker compose -f docker-compose.cpu.yml up -d --build
	@echo ""
	@echo "✅ Container started (CPU mode)!"
	@echo "   Note: Qwen3-TTS is ~10x slower on CPU"
	@echo "   Test with: make test"

# ============================================================================
# Local Development (Python venv - no Docker)
# ============================================================================

VENV_DIR := .venv
PYTHON := python3

venv:
	@echo "🐍 Creating Python virtual environment..."
	@if [ ! -d "$(VENV_DIR)" ]; then \
		$(PYTHON) -m venv $(VENV_DIR); \
		echo "✅ Virtual environment created at $(VENV_DIR)"; \
	else \
		echo "ℹ️  Virtual environment already exists at $(VENV_DIR)"; \
	fi
	@echo ""
	@echo "📦 Installing dependencies..."
	$(VENV_DIR)/bin/pip install --upgrade pip
	$(VENV_DIR)/bin/pip install -r requirements.txt
	@echo ""
	@echo "✅ Setup complete!"
	@echo ""
	@echo "To activate manually:"
	@echo "  source $(VENV_DIR)/bin/activate"
	@echo ""
	@echo "To run the server:"
	@echo "  make venv-run"
	@echo ""
	@echo "Or run directly:"
	@echo "  $(VENV_DIR)/bin/python speech.py"

venv-run:
	@echo "🚀 Starting uncloseai-speech server..."
	@if [ ! -d "$(VENV_DIR)" ]; then \
		echo "❌ Virtual environment not found. Run 'make venv' first."; \
		exit 1; \
	fi
	@[ -d "config" ] || mkdir -p config
	@[ -d "voices" ] || mkdir -p voices
	@echo ""
	@echo "Server starting on http://localhost:8000"
	@echo "Qwen3-TTS model will download on first request (~3.4GB)"
	@echo ""
	$(VENV_DIR)/bin/python speech.py

venv-clean:
	@echo "🧹 Removing virtual environment..."
	rm -rf $(VENV_DIR)
	@echo "✅ Virtual environment removed"

restart:
	@echo "🔄 Rebuilding and restarting container on $(REMOTE_HOST)..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose up -d --build"

stop:
	@echo "🛑 Stopping container on $(REMOTE_HOST)..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose down"

start:
	@echo "▶️  Starting container on $(REMOTE_HOST)..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose up -d"

clean: stop
	@echo "🧹 Removing container..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose down -v"

logs:
	@echo "📋 Tailing logs from $(REMOTE_HOST)..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker logs -f $(CONTAINER_NAME)"

test: test-qwen

test-qwen:
	@echo "🧪 Testing Qwen3-TTS endpoint (default model)..."
	curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
		-H "Content-Type: application/json" \
		-d '{"model":"tts-1-qwen","voice":"alloy","input":"Raccoon mission TTS test with Qwen three"}' \
		-o /tmp/qwen_test.mp3
	@echo "✅ Test complete! Playing audio..."
	@firefox /tmp/qwen_test.mp3 || mpv /tmp/qwen_test.mp3 || echo "Install firefox or mpv to play audio"

voices: voices-qwen
	@echo "✅ Qwen3-TTS ready (model downloads automatically on first use)"

voices-qwen:
	@echo "🎤 Qwen3-TTS models download automatically on first use"
	@echo "   Model: Qwen/Qwen3-TTS-12Hz-1.7B-Base (~3.4GB)"
	@echo "   The model will be cached in /app/voices/hub/"
	@echo ""
	@echo "To pre-download, run: make test-qwen"

voices-all: voices-qwen voices-piper voices-xtts voices-silero
	@echo "✅ All voices downloaded (Qwen, Piper, XTTS, Silero)!"

voices-piper:
	@echo "🎤 Downloading all Piper voices..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
		set -e; \
		BASE_URL=\"https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0\"; \
		download_voice() { \
			local path=\"\$$1\"; \
			local name=\"\$$2\"; \
			mkdir -p \"/app/voices/\$$path\"; \
			cd \"/app/voices/\$$path\"; \
			echo \"Downloading \$$name...\"; \
			curl -f -L \"\$$BASE_URL/\$$path/\$$name.onnx\" -o \"\$$name.onnx\" || echo \"Failed to download \$$name.onnx\"; \
			curl -f -L \"\$$BASE_URL/\$$path/\$$name.onnx.json\" -o \"\$$name.onnx.json\" || echo \"Failed to download \$$name.onnx.json\"; \
		}; \
		echo \"=== Downloading English US voices ===\"; \
		download_voice \"en/en_US/libritts_r/medium\" \"en_US-libritts_r-medium\"; \
		download_voice \"en/en_US/amy/medium\" \"en_US-amy-medium\"; \
		download_voice \"en/en_US/arctic/medium\" \"en_US-arctic-medium\"; \
		download_voice \"en/en_US/bryce/medium\" \"en_US-bryce-medium\"; \
		download_voice \"en/en_US/danny/low\" \"en_US-danny-low\"; \
		download_voice \"en/en_US/hfc_female/medium\" \"en_US-hfc_female-medium\"; \
		download_voice \"en/en_US/hfc_male/medium\" \"en_US-hfc_male-medium\"; \
		download_voice \"en/en_US/joe/medium\" \"en_US-joe-medium\"; \
		download_voice \"en/en_US/john/medium\" \"en_US-john-medium\"; \
		download_voice \"en/en_US/kathleen/low\" \"en_US-kathleen-low\"; \
		download_voice \"en/en_US/kristin/medium\" \"en_US-kristin-medium\"; \
		download_voice \"en/en_US/kusal/medium\" \"en_US-kusal-medium\"; \
		download_voice \"en/en_US/l2arctic/medium\" \"en_US-l2arctic-medium\"; \
		download_voice \"en/en_US/lessac/medium\" \"en_US-lessac-medium\"; \
		download_voice \"en/en_US/libritts/high\" \"en_US-libritts-high\"; \
		download_voice \"en/en_US/ljspeech/medium\" \"en_US-ljspeech-medium\"; \
		download_voice \"en/en_US/norman/medium\" \"en_US-norman-medium\"; \
		download_voice \"en/en_US/reza_ibrahim/medium\" \"en_US-reza_ibrahim-medium\"; \
		download_voice \"en/en_US/ryan/high\" \"en_US-ryan-high\"; \
		download_voice \"en/en_US/sam/medium\" \"en_US-sam-medium\"; \
		echo \"=== Downloading English GB voices ===\"; \
		download_voice \"en/en_GB/northern_english_male/medium\" \"en_GB-northern_english_male-medium\"; \
		download_voice \"en/en_GB/alan/medium\" \"en_GB-alan-medium\"; \
		download_voice \"en/en_GB/alba/medium\" \"en_GB-alba-medium\"; \
		download_voice \"en/en_GB/aru/medium\" \"en_GB-aru-medium\"; \
		download_voice \"en/en_GB/cori/medium\" \"en_GB-cori-medium\"; \
		download_voice \"en/en_GB/jenny_dioco/medium\" \"en_GB-jenny_dioco-medium\"; \
		download_voice \"en/en_GB/semaine/medium\" \"en_GB-semaine-medium\"; \
		download_voice \"en/en_GB/southern_english_female/low\" \"en_GB-southern_english_female-low\"; \
		download_voice \"en/en_GB/vctk/medium\" \"en_GB-vctk-medium\"; \
		echo \"=== All Piper voices downloaded! ===\"'"
	@echo "✅ All Piper voices downloaded!"

voices-xtts:
	@echo "🎤 Downloading XTTS speaker samples..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c 'cd /app && ./scripts/download_samples.sh'"
	@echo "✅ XTTS speaker samples downloaded!"

voices-kokoro:
	@echo "🎤 Downloading Kokoro TTS models..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
		mkdir -p /app/voices/kokoro && \
		cd /app/voices/kokoro && \
		huggingface-cli download hexgrad/kokoro-82m --local-dir .'"
	@echo "✅ Kokoro models downloaded!"

test-kokoro:
	@echo "🧪 Testing Kokoro fast synthesis..."
	curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
		-H "Content-Type: application/json" \
		-d '{"model":"tts-1-kokoro","voice":"alloy","input":"Testing Kokoro fast decoder synthesis"}' \
		-o /tmp/kokoro_test.mp3
	@echo "✅ Test complete! Playing audio..."
	@firefox /tmp/kokoro_test.mp3 || mpv /tmp/kokoro_test.mp3 || echo "Install firefox or mpv to play audio"

test-xtts:
	@echo "🧪 Testing XTTS HD endpoint (this may take 1-2 minutes on first run)..."
	curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
		-H "Content-Type: application/json" \
		-d '{"model":"tts-1-hd","voice":"alloy","input":"Testing XTTS high definition"}' \
		-o /tmp/xtts_test.mp3
	@echo "✅ Test complete! Playing audio..."
	@firefox /tmp/xtts_test.mp3 || mpv /tmp/xtts_test.mp3 || echo "Install firefox or mpv to play audio"

push-all:
	@echo "🚀 Pushing to all remotes..."
	git push origin main
	git push github main
	@echo "✅ Pushed to origin and github!"

voices-silero:
	@echo "🎤 Downloading Silero TTS models..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
		cd /app/voices && \
		python3 -c \"import torch; \
		for lang in [\"\"en\"\", \"\"ru\"\", \"\"de\"\", \"\"es\"\", \"\"fr\"\"]: \
			model, *_ = torch.hub.load(repo_or_dir=\"\"snakers4/silero-models\"\", model=\"\"silero_tts\"\", language=lang, speaker=\"\"v4_\"\"+lang if lang==\"\"en\"\" else \"\"v3_\"\"+lang); \
			print(f\"\"Downloaded Silero {lang}\"\")\"'"
	@echo "✅ Silero models downloaded!"

test-silero:
	@echo "🧪 Testing Silero endpoint..."
	curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
		-H "Content-Type: application/json" \
		-d '{"model":"tts-1-silero","voice":"alloy","input":"Testing Silero fast synthesis"}' \
		-o /tmp/silero_test.mp3
	@echo "✅ Test complete! Playing audio..."
	@firefox /tmp/silero_test.mp3 || mpv /tmp/silero_test.mp3 || echo "Install firefox or mpv to play audio"

voices-chatterbox:
	@echo "🎤 Downloading Chatterbox models..."
	ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
		mkdir -p /app/voices/chatterbox && \
		cd /app/voices/chatterbox && \
		huggingface-cli download resemble-ai/chatterbox --local-dir .'"
	@echo "✅ Chatterbox models downloaded!"

test-chatterbox:
	@echo "🧪 Testing Chatterbox with emotion control..."
	curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
		-H "Content-Type: application/json" \
		-d '{"model":"tts-1-chatter","voice":"alloy","input":"Testing emotional speech synthesis"}' \
		-o /tmp/chatterbox_test.mp3
	@echo "✅ Test complete! Playing audio..."
	@firefox /tmp/chatterbox_test.mp3 || mpv /tmp/chatterbox_test.mp3 || echo "Install firefox or mpv to play audio"

hydrate:
	@echo "🦝 Hydrating all TTS models by testing ALL voices..."
	@echo "This will test all 227 voices across 4 engines (Piper, XTTS, Silero, Kokoro)"
	@echo ""
	@mkdir -p /tmp/hydrate_test
	@curl -s http://$(REMOTE_HOST):8000/v1/voices | jq -r '.data[] as $$model | $$model.voices[] | "\($$model.id):\(.)"' > /tmp/hydrate_voices.txt
	@TOTAL=$$(wc -l < /tmp/hydrate_voices.txt); \
	COUNT=0; \
	FAILED=0; \
	START_TIME=$$(date +%s); \
	while IFS=: read -r MODEL VOICE; do \
		COUNT=$$((COUNT + 1)); \
		printf "[%3d/%3d] Testing %-20s %-30s ... " "$$COUNT" "$$TOTAL" "$$MODEL" "$$VOICE"; \
		if curl -s -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
			-H "Content-Type: application/json" \
			-d "{\"voice\":\"$$VOICE\",\"input\":\"Hydration test\"}" \
			-o /tmp/hydrate_test/$${MODEL}_$${VOICE}.mp3 2>&1 | grep -q "error"; then \
			echo "❌ FAILED"; \
			FAILED=$$((FAILED + 1)); \
		else \
			SIZE=$$(stat -c%s /tmp/hydrate_test/$${MODEL}_$${VOICE}.mp3 2>/dev/null || echo 0); \
			if [ "$$SIZE" -gt 1000 ]; then \
				echo "✅ OK ($${SIZE} bytes)"; \
			else \
				echo "⚠️  SMALL ($${SIZE} bytes)"; \
				FAILED=$$((FAILED + 1)); \
			fi; \
		fi; \
	done < /tmp/hydrate_voices.txt; \
	END_TIME=$$(date +%s); \
	DURATION=$$((END_TIME - START_TIME)); \
	echo ""; \
	echo "🎉 Hydration complete!"; \
	echo "   Total voices: $$TOTAL"; \
	echo "   Successful: $$((TOTAL - FAILED))"; \
	echo "   Failed: $$FAILED"; \
	echo "   Duration: $${DURATION}s"; \
	echo "   Output: /tmp/hydrate_test/"

load-test:
	@echo "🚀 Load testing TTS service with random concurrent requests..."
	@echo "This will send 100 concurrent requests with random voices across all models"
	@echo ""
	@mkdir -p /tmp/load_test
	@curl -s http://$(REMOTE_HOST):8000/v1/voices | jq -r '.data[] as $$model | $$model.voices[] | "\($$model.id):\(.)"' > /tmp/load_test_voices.txt
	@TOTAL_VOICES=$$(wc -l < /tmp/load_test_voices.txt); \
	REQUESTS=100; \
	CONCURRENT=10; \
	echo "Available voices: $$TOTAL_VOICES"; \
	echo "Total requests: $$REQUESTS"; \
	echo "Concurrent: $$CONCURRENT"; \
	echo ""; \
	START_TIME=$$(date +%s); \
	seq 1 $$REQUESTS | xargs -P$$CONCURRENT -I{} bash -c " \
		TOTAL_VOICES=\$$(wc -l < /tmp/load_test_voices.txt); \
		LINE=\$$((RANDOM % \$$TOTAL_VOICES + 1)); \
		VOICE_SPEC=\$$(sed -n \"\$${LINE}p\" /tmp/load_test_voices.txt); \
		MODEL=\$$(echo \$$VOICE_SPEC | cut -d: -f1); \
		VOICE=\$$(echo \$$VOICE_SPEC | cut -d: -f2); \
		NUM={}; \
		START=\$$(date +%s%3N); \
		if curl -s -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
			-H 'Content-Type: application/json' \
			-d '{\"model\":\"'\$$MODEL'\",\"voice\":\"'\$$VOICE'\",\"input\":\"Load test number '\$$NUM'\"}' \
			-o /tmp/load_test/request_\$${NUM}.mp3 2>&1; then \
			END=\$$(date +%s%3N); \
			DURATION=\$$((END - START)); \
			SIZE=\$$(stat -c%s /tmp/load_test/request_\$${NUM}.mp3 2>/dev/null || echo 0); \
			printf '[%3d] %-20s %-25s %5dms %6d bytes\n' \"\$$NUM\" \"\$$MODEL\" \"\$$VOICE\" \"\$$DURATION\" \"\$$SIZE\"; \
		else \
			printf '[%3d] %-20s %-25s FAILED\n' \"\$$NUM\" \"\$$MODEL\" \"\$$VOICE\"; \
		fi \
	"; \
	END_TIME=$$(date +%s); \
	DURATION=$$((END_TIME - START_TIME)); \
	SUCCESS=$$(ls /tmp/load_test/*.mp3 2>/dev/null | wc -l); \
	VALID=$$(find /tmp/load_test -name '*.mp3' -size +1000c 2>/dev/null | wc -l); \
	echo ""; \
	echo "🎉 Load test complete!"; \
	echo "   Total requests: $$REQUESTS"; \
	echo "   Files created: $$SUCCESS"; \
	echo "   Valid audio (>1KB): $$VALID"; \
	echo "   Failed: $$((REQUESTS - VALID))"; \
	echo "   Duration: $${DURATION}s"; \
	echo "   Avg: $$((DURATION * 1000 / REQUESTS))ms per request"; \
	echo "   Throughput: $$((REQUESTS / DURATION)) req/s"; \
	echo "   Output: /tmp/load_test/"
