// SPEC: PJ2026-03 PikaOA v0.9.
import type { PikaoaRuntimeSpec } from "./pikaoa-runtime";

export interface PikaoaRuntimeRenderContext {
  instanceId: string;
  commit: string;
  namespace: string;
  apiImage: string;
  workerImage: string;
  webImage: string;
  initializerImage: string;
}

export interface PikaoaRuntimeManifestOptions {
  initializerHook?: "argo-presync";
}

const TARGET_LABEL = "pikaoa.unidesk.io/target";
const INSTANCE_LABEL = "pikaoa.unidesk.io/instance";

export function renderPikaoaRuntimeManifest(
  target: PikaoaRuntimeSpec,
  context: PikaoaRuntimeRenderContext,
  options: PikaoaRuntimeManifestOptions,
): Record<string, unknown>[] {
  const labels = ownershipLabels(target, context);
  const apiSelector = componentSelector("api", context.instanceId);
  const workerSelector = componentSelector("worker", context.instanceId);
  const webSelector = componentSelector("web", context.instanceId);
  const initializerSelector = componentSelector("initializer", context.instanceId);
  const prometheusPodLabels = target.observability.prometheusScrape ? {
    [target.observability.prometheusSelector.key]: target.observability.prometheusSelector.value,
  } : {};
  const commonPodAnnotations = (path: string, port: number): Record<string, string> => target.observability.prometheusScrape ? {
    "prometheus.io/scrape": "true",
    "prometheus.io/path": path,
    "prometheus.io/port": String(port),
  } : {};
  const initializerAnnotations = options.initializerHook === "argo-presync" ? {
    "argocd.argoproj.io/hook": "PreSync",
    "argocd.argoproj.io/hook-delete-policy": "BeforeHookCreation,HookSucceeded",
    "argocd.argoproj.io/sync-wave": "-1",
  } : {};
  const runtimeConfigAnnotations = options.initializerHook === "argo-presync" ? {
    "argocd.argoproj.io/hook": "PreSync",
    "argocd.argoproj.io/hook-delete-policy": "BeforeHookCreation",
    "argocd.argoproj.io/sync-wave": "-2",
  } : {};
  return [
    {
      apiVersion: "v1", kind: "Namespace", metadata: { name: context.namespace, labels, annotations: namespaceAnnotations(target, context) },
    },
    {
      apiVersion: "v1", kind: "ConfigMap", metadata: { name: target.runtime.configMapName, namespace: context.namespace, labels, annotations: runtimeConfigAnnotations },
      data: { "pikaoa.yaml": runtimeConfigData(target, context) },
    },
    {
      apiVersion: "v1", kind: "PersistentVolumeClaim", metadata: { name: target.runtime.attachment.claimName, namespace: context.namespace, labels },
      spec: {
        accessModes: target.runtime.attachment.accessModes,
        resources: { requests: { storage: target.runtime.attachment.storageRequest } },
        ...(target.runtime.attachment.storageClassName === null ? {} : { storageClassName: target.runtime.attachment.storageClassName }),
      },
    },
    {
      apiVersion: "v1", kind: "Service", metadata: { name: target.runtime.apiServiceName, namespace: context.namespace, labels: { ...labels, ...apiSelector } },
      spec: { selector: apiSelector, ports: [{ name: "http", port: target.runtime.apiPort, targetPort: target.runtime.apiPort }] },
    },
    {
      apiVersion: "v1", kind: "Service", metadata: { name: target.exposure.serviceName, namespace: context.namespace, labels: { ...labels, ...webSelector } },
      spec: {
        type: target.exposure.serviceType,
        selector: webSelector,
        ports: [{ name: "http", port: target.runtime.webPort, targetPort: target.runtime.webPort, nodePort: target.exposure.port }],
      },
    },
    {
      apiVersion: "batch/v1", kind: "Job",
      metadata: { name: target.initializer.jobName, namespace: context.namespace, labels: { ...labels, ...initializerSelector }, annotations: initializerAnnotations },
      spec: {
        backoffLimit: target.initializer.backoffLimit,
        template: {
          metadata: { labels: { ...labels, ...initializerSelector } },
          spec: {
            restartPolicy: "Never",
            containers: [{
              name: "initializer", image: context.initializerImage, imagePullPolicy: target.source.pullPolicy,
              command: target.initializer.command,
              resources: target.runtime.resources.initializer,
              env: [
                { name: "PIKAOA_CONFIG", value: "/etc/pikaoa/pikaoa.yaml" },
                { name: "DATABASE_URL", valueFrom: { secretKeyRef: { name: target.runtime.secretName, key: target.database.connection.targetKey } } },
              ],
              volumeMounts: [{ name: "runtime", mountPath: "/etc/pikaoa", readOnly: true }],
            }],
            volumes: [{ name: "runtime", configMap: { name: target.runtime.configMapName, items: [{ key: "pikaoa.yaml", path: "pikaoa.yaml" }] } }],
          },
        },
      },
    },
    deployment(target, context, "api", context.apiImage, apiSelector, target.runtime.apiPort, prometheusPodLabels, commonPodAnnotations(target.observability.apiMetricsPath, target.runtime.apiPort), applicationEnv(target), target.probes.apiLivenessPath, target.probes.apiReadinessPath),
    deployment(target, context, "worker", context.workerImage, workerSelector, target.runtime.workerMetricsPort, prometheusPodLabels, commonPodAnnotations(target.observability.workerMetricsPath, target.runtime.workerMetricsPort), applicationEnv(target), target.probes.workerLivenessPath, target.probes.workerReadinessPath),
    deployment(target, context, "web", context.webImage, webSelector, target.runtime.webPort, {}, {}, [
      { name: target.runtime.webApiUpstreamEnv, value: `http://${target.runtime.apiServiceName}.${context.namespace}.svc.cluster.local:${target.runtime.apiPort}` },
      { name: "PIKAOA_MAX_UPLOAD_BYTES", value: String(target.runtime.attachment.maxBytes) },
    ], target.probes.webLivenessPath, target.probes.webReadinessPath),
  ];
}

function applicationEnv(target: PikaoaRuntimeSpec): Array<Record<string, unknown>> {
  return [
    { name: "PIKAOA_CONFIG", value: "/etc/pikaoa/pikaoa.yaml" },
    { name: "DATABASE_URL", valueFrom: { secretKeyRef: { name: target.runtime.secretName, key: target.database.connection.targetKey } } },
    { name: "PIKAOA_SESSION_SECRET", valueFrom: { secretKeyRef: { name: target.runtime.secretName, key: target.runtime.sessionSecret.targetKey } } },
    { name: "OA_ADMIN_TOKEN", valueFrom: { secretKeyRef: { name: target.runtime.secretName, key: target.runtime.adminToken.targetKey } } },
    { name: "PIKAOA_BOOTSTRAP_ADMIN_USERNAME", value: target.runtime.administrator.username },
    { name: "PIKAOA_BOOTSTRAP_ADMIN_PASSWORD", valueFrom: { secretKeyRef: { name: target.runtime.secretName, key: target.runtime.administrator.password.targetKey } } },
    { name: "PIKAOA_BOOTSTRAP_EMPLOYEE_USERNAME", value: target.runtime.employee.username },
    { name: "PIKAOA_BOOTSTRAP_EMPLOYEE_PASSWORD", valueFrom: { secretKeyRef: { name: target.runtime.secretName, key: target.runtime.employee.password.targetKey } } },
  ];
}

export function ownershipLabels(target: PikaoaRuntimeSpec, context: PikaoaRuntimeRenderContext): Record<string, string> {
  const release = target.source.branch === "release";
  return {
    "app.kubernetes.io/name": "pikaoa",
    "app.kubernetes.io/part-of": release ? "pikaoa-release-runtime" : "pikaoa-development-runtime",
    "app.kubernetes.io/managed-by": target.fieldManager,
    [release ? "pikaoa.unidesk.io/release-runtime" : "pikaoa.unidesk.io/development-runtime"]: "true",
    [TARGET_LABEL]: target.id,
    [INSTANCE_LABEL]: context.instanceId,
  };
}

export function componentSelector(component: string, instanceId: string): Record<string, string> {
  return { "app.kubernetes.io/name": "pikaoa", "app.kubernetes.io/component": component, [INSTANCE_LABEL]: instanceId };
}

export function namespaceAnnotations(target: PikaoaRuntimeSpec, context: PikaoaRuntimeRenderContext): Record<string, string> {
  return {
    "pikaoa.unidesk.io/source-repository": target.source.repository,
    "pikaoa.unidesk.io/source-commit": context.commit,
    "pikaoa.unidesk.io/delivery-managed": "true",
  };
}

function deployment(
  target: PikaoaRuntimeSpec,
  context: PikaoaRuntimeRenderContext,
  component: "api" | "worker" | "web",
  image: string,
  selector: Record<string, string>,
  port: number,
  podLabels: Record<string, string>,
  annotations: Record<string, string>,
  env: Array<Record<string, unknown>>,
  livenessPath: string,
  readinessPath: string,
): Record<string, unknown> {
  const labels = ownershipLabels(target, context);
  return {
    apiVersion: "apps/v1", kind: "Deployment", metadata: { name: `pikaoa-${component}`, namespace: context.namespace, labels: { ...labels, ...selector } },
    spec: {
      replicas: target.runtime.replicas[component], selector: { matchLabels: selector },
      template: {
        metadata: { labels: { ...labels, ...selector, ...podLabels }, annotations },
        spec: {
          ...(component === "web" ? {} : { securityContext: { fsGroup: target.runtime.attachment.fsGroup } }),
          containers: [{
            name: component, image, imagePullPolicy: target.source.pullPolicy, env, resources: target.runtime.resources[component],
            ports: [{ name: component === "worker" ? "metrics" : "http", containerPort: port }],
            volumeMounts: [
              ...(component === "web" ? [] : [{ name: "runtime", mountPath: "/etc/pikaoa", readOnly: true }]),
              ...(component === "web" ? [] : [{ name: target.runtime.attachment.claimName, mountPath: target.runtime.attachment.storageRoot }]),
            ],
            livenessProbe: { httpGet: { path: livenessPath, port }, periodSeconds: 5, failureThreshold: 12 },
            readinessProbe: { httpGet: { path: readinessPath, port }, periodSeconds: 3, failureThreshold: 20 },
          }],
          volumes: [
            ...(component === "web" ? [] : [{ name: "runtime", configMap: { name: target.runtime.configMapName, items: [{ key: "pikaoa.yaml", path: "pikaoa.yaml" }] } }]),
            ...(component === "web" ? [] : [{ name: target.runtime.attachment.claimName, persistentVolumeClaim: { claimName: target.runtime.attachment.claimName } }]),
          ],
        },
      },
    },
  };
}

function runtimeConfigData(target: PikaoaRuntimeSpec, context: PikaoaRuntimeRenderContext): string {
  return [
    "api:",
    `  listen: 0.0.0.0:${target.runtime.apiPort}`,
    "worker:",
    `  metricsListen: 0.0.0.0:${target.runtime.workerMetricsPort}`,
    "  outbox:",
    `    batchSize: ${target.runtime.outboxBatchSize}`,
    `    maxAttempts: ${target.runtime.outboxMaxAttempts}`,
    `    retryDelay: ${target.runtime.outboxRetryDelay}`,
    "temporal:",
    `  address: ${target.temporal.serviceRef.name}.${target.temporal.serviceRef.namespace}.svc.cluster.local:${target.temporal.serviceRef.port}`,
    `  namespace: ${target.temporal.logicalNamespace}`,
    `  taskQueue: ${target.temporal.taskQueue}`,
    `  workflowId: ${target.temporal.workflowId}`,
    `  drainInterval: ${target.temporal.drainInterval}`,
    `  activityTimeout: ${target.temporal.activityTimeout}`,
    `  retryInitialInterval: ${target.temporal.retryInitialInterval}`,
    `  retryMaximumInterval: ${target.temporal.retryMaximumInterval}`,
    `  retryMaximumAttempts: ${target.temporal.retryMaximumAttempts}`,
    `  continueAsNewEvery: ${target.temporal.continueAsNewEvery}`,
    "native:",
    `  stateDir: ${JSON.stringify(target.native.stateDir)}`,
    `  logDir: ${JSON.stringify(target.native.logDir)}`,
    `  apiCommand: ${JSON.stringify(target.native.api.command)}`,
    `  workerCommand: ${JSON.stringify(target.native.worker.command)}`,
    "database:",
    '  url: ""',
    "identity:",
    `  sessionTTL: ${target.runtime.sessionTTL}`,
    "attachment:",
    `  storageRoot: ${JSON.stringify(target.runtime.attachment.storageRoot)}`,
    `  maxBytes: ${target.runtime.attachment.maxBytes}`,
    "observability:",
    `  serviceName: ${target.source.branch === "release" ? "pikaoa" : `pikaoa-dev-${context.instanceId}`}`,
    `  otlpEndpoint: ${JSON.stringify(target.observability.otlpEndpoint)}`,
    `shutdownTimeout: ${target.runtime.shutdownTimeout}`,
    "",
  ].join("\n");
}
