# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Email: Georgescottfoley@proton.me
# Licensed under the MIT License - see LICENSE file for details

"""
Compose file generator — produces ``familiar-compose.yml`` from service specs.

Convenience for users who prefer managing services via ``podman-compose``
or ``docker compose`` instead of the dashboard UI.
"""

import os
from pathlib import Path
from typing import Dict, List, Optional

import yaml

from familiar.services.specs import SERVICE_SPECS, ServiceType


def generate_compose(
    service_keys: Optional[List[str]] = None,
    runtime: str = "podman",
) -> str:
    """Generate a Compose YAML string for the requested services.

    Args:
        service_keys: List of service keys to include. ``None`` includes all
            container services.
        runtime: ``"podman"`` or ``"docker"`` — only affects the header comment.

    Returns:
        YAML string suitable for writing to ``familiar-compose.yml``.
    """
    if service_keys is None:
        service_keys = [
            k for k, s in SERVICE_SPECS.items()
            if s.service_type == ServiceType.CONTAINER
        ]

    home = str(Path.home())
    services: Dict[str, dict] = {}

    for key in service_keys:
        spec = SERVICE_SPECS.get(key)
        if not spec or spec.service_type != ServiceType.CONTAINER:
            continue

        svc: dict = {
            "image": spec.image,
            "container_name": spec.default_container_name,
            "restart": "unless-stopped",
        }

        if spec.ports:
            svc["ports"] = [
                f"{host}:{container}"
                for host, container in spec.ports.items()
            ]

        if spec.volumes:
            resolved = spec.get_resolved_volumes(home)
            svc["volumes"] = [
                f"{hp}:{cp}"
                for hp, cp in resolved.items()
            ]

        if spec.env_vars:
            svc["environment"] = dict(spec.env_vars)

        services[key] = svc

    compose: dict = {
        "version": "3.8",
        "services": services,
    }

    header = (
        f"# Familiar self-hosted services — generated for {runtime}\n"
        f"# Re-generate via: familiar-server compose\n"
        f"# Run with: {runtime}-compose -f familiar-compose.yml up -d\n"
    )

    return header + yaml.dump(compose, default_flow_style=False, sort_keys=False)


def write_compose_file(
    output_path: Optional[str] = None,
    service_keys: Optional[List[str]] = None,
    runtime: str = "podman",
) -> str:
    """Write a ``familiar-compose.yml`` file to disk.

    Args:
        output_path: Destination path. Defaults to ``~/.familiar/services/familiar-compose.yml``.
        service_keys: Service keys to include (``None`` = all container services).
        runtime: ``"podman"`` or ``"docker"``.

    Returns:
        The absolute path to the written file.
    """
    if output_path is None:
        output_path = os.path.join(
            str(Path.home()), ".familiar", "services", "familiar-compose.yml"
        )

    content = generate_compose(service_keys=service_keys, runtime=runtime)
    Path(output_path).parent.mkdir(parents=True, exist_ok=True)

    with open(output_path, "w") as f:
        f.write(content)

    return os.path.abspath(output_path)
