"""Helm chart composer for NIKAME.

Generates a standard Helm chart structure (Chart.yaml, values.yaml, templates/)
from the resolved blueprint.
"""

from __future__ import annotations

import yaml

from nikame.blueprint.engine import Blueprint


def generate_helm_chart(blueprint: Blueprint) -> dict[str, str]:
    """Generate a dynamic Helm chart based on the Blueprint."""
    chart_name = blueprint.project_name.replace("_", "-")
    files: dict[str, str] = {}

    # 1. Chart.yaml
    chart_yaml = {
        "apiVersion": "v2",
        "name": chart_name,
        "description": f"Helm chart for {blueprint.project_name} - generated by NIKAME",
        "type": "application",
        "version": "0.1.0",
        "appVersion": "1.0.0",
    }
    files["Chart.yaml"] = yaml.dump(chart_yaml, sort_keys=False)

    # 2. Extract values.yaml
    values = {
        "global": {
            "domain": blueprint.modules[0].ctx.domain if blueprint.modules else "",
            "environment": blueprint.modules[0].ctx.environment if blueprint.modules else "production",
        },
    }

    for mod in blueprint.modules:
        mod_values = {
            "enabled": True,
            "replicaCount": 2 if mod.ctx.environment == "production" else 1,
            "resources": mod.resource_requirements(),
        }
        values[mod.NAME] = mod_values

    files["values.yaml"] = yaml.dump(values, sort_keys=False)

    # 3. Helpers (_helpers.tpl)
    files["templates/_helpers.tpl"] = f"""{{/* Common labels */}}
{{{{- define "{chart_name}.labels" -}}}}
app.kubernetes.io/name: {{{{ .Chart.Name }}}}
app.kubernetes.io/instance: {{{{ .Release.Name }}}}
nikame.project: {blueprint.project_name}
{{{{- end }}}}
"""

    # 4. Templates (Parameterization)
    all_manifests = blueprint.k8s_manifests()
    for i, manifest in enumerate(all_manifests):
        kind = manifest.get("kind", "Resource")
        name = manifest.get("metadata", {}).get("name")
        # Heuristic to find which module it belongs to
        owner_module = manifest.get("metadata", {}).get("labels", {}).get("nikame.module", "global")

        filename = f"templates/{owner_module}-{kind.lower()}-{name}.yaml"

        # Simple parameterization: replace specific values with placeholders
        manifest_str = yaml.dump(manifest, sort_keys=False)

        # 1. Replicas
        if kind in ["Deployment", "StatefulSet"]:
            manifest_str = manifest_str.replace("replicas: 1", f"replicas: {{{{ .Values.{owner_module}.replicaCount | default 1 }}}}")
            manifest_str = manifest_str.replace("replicas: 2", f"replicas: {{{{ .Values.{owner_module}.replicaCount | default 2 }}}}")

        # 2. Ingress Host
        if kind == "Ingress" and blueprint.modules[0].ctx.domain:
            domain = blueprint.modules[0].ctx.domain
            manifest_str = manifest_str.replace(f"host: {domain}", "host: {{ .Values.global.domain }}")
            manifest_str = manifest_str.replace(f"host: console.{domain}", "host: console.{{ .Values.global.domain }}")
            manifest_str = manifest_str.replace(f"- {domain}", "- {{ .Values.global.domain }}")

        # 3. Resources (replace the whole block if found)
        if "resources:" in manifest_str:
            # We use a bit of a hack here to inject Helm values into the resource block
            # In a more robust implementation, we would use a proper YAML parser with anchors
            res_path = f".Values.{owner_module}.resources"
            manifest_str = manifest_str.replace("resources: {}", f"resources: {{{{ toYaml {res_path} | nindent 10 }}}}")

        files[filename] = manifest_str

    return files
