# 1. On récupère la version la plus récente d'UV
FROM ghcr.io/astral-sh/uv:latest AS uv_source

# 2. Image de base stable
FROM debian:stable-slim

# Disable Python stdout buffering to ensure logs are printed immediately
ENV PYTHONUNBUFFERED=1

# Install system dependencies in one layer, clear APT cache
# tini reaps orphaned zombie processes (MCP stdio subprocesses, git, bun, etc.)
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        build-essential python3 ripgrep ffmpeg gcc python3-dev libffi-dev procps git openssh-client docker-cli tini \
        curl poppler-utils imagemagick \
        texlive-latex-base texlive-latex-extra texlive-fonts-recommended texlive-xetex texlive-science \
        qemu-user-static binfmt-support qemu-user-binfmt \
        emacs-nox \
        libportaudio2 \
        hipcc espeak-ng && \
    rm -rf /var/lib/apt/lists/*

# Création de l'utilisateur 'hermes' directement avec les bons accès
RUN useradd -u 10000 -m -d /opt/data hermes

# Copie d'uv (dernière version)
COPY --chmod=0755 --from=uv_source /uv /usr/local/bin/

WORKDIR /opt/hermes

# On donne la propriété du dossier de travail à l'utilisateur hermes
RUN chown hermes:hermes /opt/hermes

# ---------- Coqui TTS venv (Python 3.11 + PyTorch ROCm) ----------
# Install Python 3.11 via uv for Coqui compatibility
RUN uv python install 3.11

# Create the coqui venv and install PyTorch ROCm + TTS
RUN uv venv --python 3.11 /opt/coqui-tts
RUN uv pip install --python /opt/coqui-tts/bin/python3 --no-cache-dir \
    torch==2.3.1+rocm5.7 \
    torchaudio==2.3.1+rocm5.7 \
    --index-url https://download.pytorch.org/whl/rocm5.7
RUN uv pip install --python /opt/coqui-tts/bin/python3 --no-cache-dir TTS setuptools

# Fix executable stack on bundled torch AMD libraries (required for ROCm)
RUN /opt/coqui-tts/bin/python3 -c "
import struct, os, glob
torch_lib = '/opt/coqui-tts/lib/python3.11/site-packages/torch/lib'
for so in glob.glob(os.path.join(torch_lib, '*.so*')):
    try:
        with open(so, 'r+b') as f:
            if f.read(4) != b'\x7fELF': continue
            f.seek(0)
            h = f.read(64)
            e_phoff = struct.unpack_from('<Q', h, 0x20)[0]
            e_phentsize = struct.unpack_from('<H', h, 0x36)[0]
            e_phnum = struct.unpack_from('<H', h, 0x38)[0]
            for i in range(e_phnum):
                f.seek(e_phoff + i * e_phentsize)
                ph = f.read(e_phentsize)
                if struct.unpack_from('<I', ph, 0)[0] == 0x6474e551:
                    flags = struct.unpack_from('<I', ph, 4)[0]
                    if flags & 1:
                        f.seek(e_phoff + i * e_phentsize + 4)
                        f.write(struct.pack('<I', flags - 1))
                    break
    except: pass
"

# Créer le wrapper Coqui synth
RUN /opt/coqui-tts/bin/python3 -c "
script = '''#!/usr/bin/env python3
import argparse, sys
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--text', required=True)
    parser.add_argument('--out', required=True)
    parser.add_argument('--model', default='tts_models/en/vctk/vits')
    parser.add_argument('--speaker', default='')
    parser.add_argument('--gpu', action='store_true', default=True)
    args = parser.parse_args()
    try:
        from TTS.api import TTS
        tts = TTS(model_name=args.model, progress_bar=False, gpu=args.gpu)
        kwargs = {'text': args.text, 'file_path': args.out}
        if args.speaker and hasattr(tts, 'speakers') and tts.speakers:
            kwargs['speaker'] = args.speaker
        tts.tts_to_file(**kwargs)
        print('OK:' + args.out)
    except Exception as e:
        print('ERROR:' + str(e), file=sys.stderr)
        sys.exit(1)
if __name__ == '__main__':
    main()
'''
with open('/opt/coqui-tts/bin/coqui_synth.py', 'w') as f:
    f.write(script)
import os; os.chmod('/opt/coqui-tts/bin/coqui_synth.py', 0o755)
"

# ---------- Hermes venv ----------
# Passer immédiatement sous l'utilisateur hermes pour tout le reste du build
USER hermes

# ---------- Source code ----------
# On copie tout le projet d'un coup sans assumer la présence de fichiers de lock spécifiques
COPY --chown=hermes:hermes . .

# ---------- Python virtualenv ----------
RUN uv venv && \
    uv pip install --no-cache-dir sounddevice numpy faster-whisper

# ---------- Patch tts_tool.py to add Coqui provider ----------
RUN /opt/hermes/.venv/bin/python3 -c "
tts_path = '/opt/hermes/.venv/lib/python3.13/site-packages/tools/tts_tool.py'
with open(tts_path) as f:
    code = f.read()
coqui_block = '''
        elif provider == \"coqui\":
            logger.info(\"Generating speech with Coqui TTS (GPU, local)...\")
            import subprocess
            coqui_python = \"/opt/coqui-tts/bin/python3\"
            coqui_script = \"/opt/coqui-tts/bin/coqui_synth.py\"
            coqui_config = tts_config.get(\"coqui\", {})
            model = coqui_config.get(\"model\", \"tts_models/en/vctk/vits\")
            use_gpu = coqui_config.get(\"use_gpu\", True)
            speaker = coqui_config.get(\"speaker\", \"\")
            cmd = [
                coqui_python, coqui_script,
                \"--text\", text,
                \"--out\", file_str,
                \"--model\", model,
            ]
            if use_gpu:
                cmd.append(\"--gpu\")
            if speaker:
                cmd.extend([\"--speaker\", speaker])
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
            if result.returncode != 0:
                stderr = result.stderr.strip()
                raise RuntimeError(f\"Coqui TTS failed: {stderr or 'unknown error'}\")
            logger.info(\"Coqui TTS audio saved: %s\", file_str)
'''
code = code.replace(
    '        else:\n            # Default: Edge TTS (free), with NeuTTS as local fallback',
    coqui_block + '        else:\n            # Default: Edge TTS (free), with NeuTTS as local fallback'
)
with open(tts_path, 'w') as f:
    f.write(code)
"

# ---------- Runtime ----------
ENV HERMES_HOME=/opt/data
ENV PATH="/opt/data/.local/bin:${PATH}"

VOLUME [ "/opt/data" ]

# Le conteneur tourne de manière ultra-sécurisée sous l'utilisateur hermes dès le départ
ENTRYPOINT [ "/usr/bin/tini", "-g", "--", "/opt/hermes/docker/entrypoint.sh" ]
