# Tiltfile for llama-agents local development
# Supports kind (default) and docker-desktop targets.
# Pass target via: tilt up -- --target=docker-desktop

config.define_string('target', args=True, usage='Cluster target: kind or docker-desktop')
config.define_string('apps-namespace', args=False, usage='Namespace for LlamaDeployment CRs and app resources. Unset = release namespace.')
cfg = config.parse()
target = cfg.get('target', 'kind')
apps_namespace = cfg.get('apps-namespace', '')

K8S_CONTEXTS = {
    'kind': 'kind-kind',
    'docker-desktop': 'docker-desktop',
}
allow_k8s_contexts(K8S_CONTEXTS[target])

# ---------------------------------------------------------------------------
# Docker images
# ---------------------------------------------------------------------------

# Control plane (Python) — Tilt auto-injects into the deployment's image: field
docker_build(
    'llama-agents-control-plane',
    context='..',
    dockerfile='../docker/Dockerfile',
    target='controlplane',
    only=[
        './packages/',
        './docker/Dockerfile',
        './pyproject.toml',
        './uv.lock',
        './README.md',
    ],
)

# Operator (Go) — Tilt auto-injects into the deployment's image: field
docker_build(
    'llama-agents-operator',
    context='..',
    dockerfile='../docker/operator.Dockerfile',
    only=[
        './operator/',
        './docker/operator.Dockerfile',
    ],
)

# App server — used by the operator at runtime (not in helm-rendered YAML).
# The operator reads repo/tag from separate env vars, so Tilt can't auto-inject.
# We build with a fixed tag and load into the cluster manually (kind only).
APPSERVER_TAG = 'tilt-dev'
APPSERVER_IMG = 'llama-agents-appserver:%s' % APPSERVER_TAG

if target == 'kind':
    _appserver_cmd = 'docker build -t %s -f ../docker/Dockerfile --target appserver .. && kind load docker-image %s --name kind' % (APPSERVER_IMG, APPSERVER_IMG)
else:
    # docker-desktop shares the Docker daemon — no load step needed
    _appserver_cmd = 'docker build -t %s -f ../docker/Dockerfile --target appserver ..' % APPSERVER_IMG

local_resource(
    'appserver-image',
    cmd=_appserver_cmd,
    deps=[
        '../packages/',
        '../docker/Dockerfile',
        '../pyproject.toml',
        '../uv.lock',
    ],
)

# ---------------------------------------------------------------------------
# Dev infrastructure
# ---------------------------------------------------------------------------

# Prometheus Operator + Prometheus instance for ServiceMonitor-based scraping.
# Installed outside Tilt's resource management to avoid label conflicts.
local(
    'tilt/scripts/install-prometheus.sh %s' % K8S_CONTEXTS[target],
    quiet=True,
)

# SeaweedFS for S3-compatible backup storage
k8s_yaml('tilt/k8s-manifests/seaweedfs.yaml')

k8s_yaml('tilt/k8s-manifests/object-storage-secrets.yaml')
k8s_yaml('tilt/k8s-manifests/backup-encryption-secrets.yaml')

# Optional control plane secrets from .env (GITHUB_APP_PRIVATE_KEY, GITHUB_APP_CLIENT_ID, GITHUB_APP_NAME, GITHUB_APP_SECRET)
if os.path.exists('../.env'):
    k8s_yaml(local('python3 tilt/env-to-secret.py', quiet=True))


# ---------------------------------------------------------------------------
# CRDs — installed via the llama-agents-crds chart so the chart is exercised
# in the dev loop. The keep annotation (default) ensures CRDs survive
# `tilt down` / `helm uninstall` and CRs are not garbage-collected.
# ---------------------------------------------------------------------------

local(
    'helm upgrade --install llama-agents-crds ../charts/llama-agents-crds -n llama-agents --create-namespace',
    quiet=True,
)

# ---------------------------------------------------------------------------
# Helm deployment
# ---------------------------------------------------------------------------

helm_sets = [
    # Controlplane + operator: repos match docker_build names so Tilt
    # auto-replaces the image: field with its content-addressed ref.
    'images.controlPlane.repository=llama-agents-control-plane',
    'images.controlPlane.tag=unused-tilt-will-replace',
    'images.operator.repository=llama-agents-operator',
    'images.operator.tag=unused-tilt-will-replace',
    # Appserver: operator reads these as env vars at runtime.
    # Fixed tag matches what local_resource loads into kind.
    'images.appserver.repository=llama-agents-appserver',
    'images.appserver.tag=%s' % APPSERVER_TAG,
    'images.appserver.pullPolicy=Never',
]
if apps_namespace:
    helm_sets.append('apps.namespace=%s' % apps_namespace)

k8s_yaml(
    helm(
        '../charts/llama-agents',
        name='llama-agents',
        namespace='llama-agents',
        values=['tilt/helm/values-dev.yaml'],
        set=helm_sets,
    ),
)

# ---------------------------------------------------------------------------
# Resource configuration and port forwards
# ---------------------------------------------------------------------------

# Control plane deployment — forward the service port to localhost:8011
k8s_resource(
    'llama-agents-control-plane',
    port_forwards='8011:8000',
)

# SeaweedFS — S3-compatible storage for backup testing
k8s_resource('seaweedfs')

# Create the S3 bucket inside SeaweedFS once it's running
local_resource(
    'seaweedfs-init',
    cmd="for i in 1 2 3 4 5; do kubectl exec -n llama-agents deploy/seaweedfs -- sh -c \"echo 's3.bucket.create -name backups' | weed shell -master=localhost:9333\" && exit 0; echo \"seaweedfs-init attempt $i failed, retrying...\"; sleep 3; done; echo 'seaweedfs-init failed after 5 attempts'; exit 1",
    resource_deps=['seaweedfs'],
)

# Operator deployment — depends on appserver image being built first
k8s_resource(
    'llama-agents-operator',
    resource_deps=['appserver-image'],
    port_forwards='8080:8080',
)

# ---------------------------------------------------------------------------
# Maintenance
# ---------------------------------------------------------------------------

# Prune orphaned containerd snapshots inside the kind node every 6 hours.
# Only relevant for kind — its containerd layers grow unbounded.
if target == 'kind':
    k8s_yaml('tilt/k8s-manifests/kind-gc-cronjob.yaml')
    k8s_resource('kind-gc', labels=['infra'])
