from __future__ import annotations

import os
import shutil
import subprocess
from datetime import datetime
from pathlib import Path

import yaml
from docx import Document
from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parent
OUTPUT_DIR = BASE_DIR / "output"
PROMPTS_FILE = BASE_DIR / "config" / "prompts.yaml"

load_dotenv(BASE_DIR / ".env")


def _transcript_to_text(transcription_data: list[dict[str, object]]) -> str:
    lines: list[str] = []
    for seg in transcription_data:
        speaker = str(seg.get("speaker", "UNBEKANNT"))
        text = str(seg.get("text", "")).strip()
        if text:
            lines.append(f"{speaker}: {text}")
    return "\n".join(lines)


def build_protocol_prompt(
    transcription_data: list[dict[str, object]],
    session_type: str,
    participants_text: str,
    context_text: str = "",
) -> str:
    with PROMPTS_FILE.open("r", encoding="utf-8") as file:
        config = yaml.safe_load(file)

    sys_prompt = config["system_prompt"]
    task_prompt = config["sitzungsarten"].get(session_type, "Erstelle ein Protokoll.")
    transcript_text = _transcript_to_text(transcription_data)

    return f"""
SYSTEMROLLE:
{sys_prompt}

AUFGABE:
{task_prompt}

TEILNEHMER & FUNKTIONEN (Nutze dies für das Namens-Mapping):
{participants_text}

ZUSÄTZLICHER KONTEXT (Traktanden, Vorprotokolle etc.):
{context_text}

TRANSKRIPT DER SITZUNG:
{transcript_text}

AUSGABE:
Erstelle ein sauber strukturiertes deutschsprachiges Sitzungsprotokoll. Schreibe nur das fertige Protokoll, keine Vorbemerkungen über das Modell oder den Prozess.
""".strip()


def _resolve_codex_bin() -> str:
    """Resolve CodexCLI also when systemd/Streamlit has a minimal PATH."""
    configured = os.getenv("CODEX_BIN")
    candidates = [configured] if configured else []
    candidates.extend([
        "codex",
        str(Path.home() / ".local" / "bin" / "codex"),
        "/usr/local/bin/codex",
    ])

    for candidate in candidates:
        if not candidate:
            continue
        if Path(candidate).is_absolute() and Path(candidate).exists():
            return candidate
        resolved = shutil.which(candidate)
        if resolved:
            return resolved

    raise RuntimeError(
        "CodexCLI nicht gefunden. Setze CODEX_BIN=/home/agent/.local/bin/codex "
        "oder installiere `codex` im PATH."
    )


def _generate_with_codex(prompt: str) -> str:
    codex_bin = _resolve_codex_bin()

    model = os.getenv("CODEX_MODEL", "gpt-5.5")
    timeout = int(os.getenv("CODEX_TIMEOUT_SECONDS", "1800"))
    command = [
        codex_bin,
        "exec",
        "--model",
        model,
        "--cd",
        str(BASE_DIR),
        "--sandbox",
        "read-only",
        "--ephemeral",
        "-",
    ]
    result = subprocess.run(
        command,
        input=prompt,
        text=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        timeout=timeout,
        check=False,
        env={
            **os.environ,
            "PATH": f"{Path.home() / '.local' / 'bin'}:/usr/local/bin:{os.environ.get('PATH', '')}",
        },
    )
    if result.returncode != 0:
        stderr = result.stderr.strip()[-2000:]
        raise RuntimeError(f"CodexCLI fehlgeschlagen (Exit {result.returncode}): {stderr}")
    output = result.stdout.strip()
    if not output:
        raise RuntimeError("CodexCLI lieferte keine Ausgabe.")
    return output


def generate_protocol_with_llm(transcription_data, session_type, participants_text, context_text=""):
    print("\n[*] Lade Prompts für ChatGPT/CodexCLI...")
    prompt = build_protocol_prompt(transcription_data, session_type, participants_text, context_text)

    if os.getenv("AUTOPROTOCOL_LLM_MOCK") == "1":
        return "Sitzungsprotokoll\n\nDies ist ein lokaler Mock-Test ohne externen LLM-Aufruf."

    print(f"[*] Sende Protokollauftrag an CodexCLI (Modell: {os.getenv('CODEX_MODEL', 'gpt-5.5')})...")
    return _generate_with_codex(prompt)


def save_llm_to_word(llm_text, original_filename):
    """Speichert den Codex/ChatGPT-Output als Word-Dokument."""
    print("[*] Erstelle finales Word-Dokument...")
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    doc = Document()
    doc.add_heading("Sitzungsprotokoll", 0)

    now = datetime.now()
    doc.add_paragraph(f"Datum der Erstellung: {now.strftime('%d.%m.%Y %H:%M')}")
    doc.add_paragraph(f"Quelle: {original_filename}")
    doc.add_paragraph("-" * 50)
    doc.add_paragraph(llm_text)

    output_filename = f"Protokoll_{now.strftime('%Y%m%d_%H%M')}.docx"
    output_path = OUTPUT_DIR / output_filename
    doc.save(str(output_path))
    return str(output_path)
