// SPEC: PJ2026-03 PikaOA v0.8.
import { existsSync } from "node:fs";
import { resolve } from "node:path";

import {
  pikaoaDevelopmentRuntimeConfigRef,
  pikaoaReleaseRuntimeConfigRef,
  resolvePikaoaReleaseRuntimeTargetByConfigRef,
  resolvePikaoaDevelopmentRuntimeTargetByConfigRef,
  type PikaoaRuntimeSpec,
} from "./pikaoa-runtime";
import { renderPikaoaRuntimeManifest, type PikaoaRuntimeRenderContext } from "./pikaoa-runtime-manifest";
import { stableJsonSha256 } from "./stable-json";

export interface PikaoaRendererBinding {
  readonly consumer: {
    readonly id: string;
    readonly node: string;
    readonly lane: string;
    readonly namespace: string;
    readonly pipeline: string;
    readonly pipelineRunPrefix: string;
    readonly sourceArtifact: {
      readonly configRef: string;
      readonly mode: string;
      readonly renderer: string;
    };
  };
  readonly repository: {
    readonly id: string;
    readonly params: Readonly<Record<string, string>>;
  };
}

export interface PikaoaRenderedPipeline {
  readonly pipeline: Record<string, unknown>;
  readonly configRef: string;
  readonly effectiveConfigSha256: string;
  readonly sourceWorktreeRemote: string;
}

export function renderPikaoaDesiredPipeline(binding: PikaoaRendererBinding, sourceWorktree: string): PikaoaRenderedPipeline {
  const release = binding.consumer.sourceArtifact.renderer === "pikaoa-release-runtime";
  const target = release
    ? resolvePikaoaReleaseRuntimeTargetByConfigRef(binding.consumer.sourceArtifact.configRef)
    : resolvePikaoaDevelopmentRuntimeTargetByConfigRef(binding.consumer.sourceArtifact.configRef);
  const configRef = release ? pikaoaReleaseRuntimeConfigRef(target.id) : pikaoaDevelopmentRuntimeConfigRef(target.id);
  if ((!release && binding.consumer.sourceArtifact.renderer !== "pikaoa-development-runtime") || binding.consumer.sourceArtifact.mode !== "embedded-pipeline-spec") {
    throw new Error(`${binding.consumer.sourceArtifact.renderer} requires embedded-pipeline-spec`);
  }
  if (binding.consumer.sourceArtifact.configRef !== configRef) {
    throw new Error(`sourceArtifact.configRef must equal resolved owning selector ${configRef}`);
  }
  assertBinding(target, binding);
  assertSourceRepositoryContract(target, sourceWorktree);
  return {
    pipeline: pipeline(target),
    configRef,
    effectiveConfigSha256: stableJsonSha256(target),
    sourceWorktreeRemote: target.source.worktreeRemote,
  };
}

export function pikaoaDevelopmentSourceWorktreeRemote(targetId: string): string {
  return resolvePikaoaDevelopmentRuntimeTargetByConfigRef(pikaoaDevelopmentRuntimeConfigRef(targetId)).source.worktreeRemote;
}

export function pikaoaReleaseSourceWorktreeRemote(targetId: string): string {
  return resolvePikaoaReleaseRuntimeTargetByConfigRef(pikaoaReleaseRuntimeConfigRef(targetId)).source.worktreeRemote;
}

function pipeline(target: PikaoaRuntimeSpec): Record<string, unknown> {
  const runtimeManifest = renderGitOpsManifest(target);
  return {
    apiVersion: "tekton.dev/v1",
    kind: "Pipeline",
    metadata: { name: target.ci.pipeline, namespace: target.ci.namespace },
    spec: {
      params: [
        { name: "revision", type: "string" },
        { name: "source-snapshot-prefix", type: "string", default: target.source.snapshotPrefix },
        { name: "git-read-url", type: "string", default: target.source.readUrl },
        { name: "gitops-read-url", type: "string", default: target.gitops.readUrl },
        { name: "gitops-write-url", type: "string", default: target.gitops.writeUrl },
        { name: "gitops-username", type: "string", default: target.gitops.credentialUsername },
        { name: "gitops-secret-name", type: "string", default: target.gitops.credentialSecretName },
      ],
      workspaces: [{ name: "workspace" }],
      tasks: [
        sourceTask(target),
        imageBuildTask(target, "api"),
        imageBuildTask(target, "worker"),
        imageBuildTask(target, "web"),
        gitOpsTask(target, runtimeManifest),
      ],
    },
  };
}

function sourceTask(target: PikaoaRuntimeSpec): Record<string, unknown> {
  return {
    name: "source",
    taskSpec: {
      params: [
        { name: "revision", type: "string" },
        { name: "source-snapshot-prefix", type: "string" },
        { name: "git-read-url", type: "string" },
        { name: "gitops-username", type: "string" },
        { name: "gitops-secret-name", type: "string" },
      ],
      workspaces: [{ name: "workspace", mountPath: "/workspace" }],
      steps: [{
        name: "checkout",
        image: target.ci.toolsImage,
        imagePullPolicy: "IfNotPresent",
        script: `#!/bin/sh
set -eu
revision="$(params.revision)"
case "$revision" in *[!0-9a-f]*|'') echo 'revision must be a full lowercase source commit' >&2; exit 2;; esac
test "\${#revision}" -eq 40
askpass=/tmp/pikaoa-source-git-askpass
cat >"$askpass" <<'ASKPASS'
#!/bin/sh
case "$1" in
  *Username*) printf '%s' "$PIKAOA_GIT_USERNAME" ;;
  *Password*) cat /var/run/pikaoa-source/token ;;
  *) exit 1 ;;
esac
ASKPASS
chmod 700 "$askpass"
export PIKAOA_GIT_USERNAME="$(params.gitops-username)"
export GIT_ASKPASS="$askpass"
export GIT_TERMINAL_PROMPT=0
rm -rf /workspace/source
git init /workspace/source
git -C /workspace/source remote add origin "$(params.git-read-url)"
git -C /workspace/source fetch --depth=1 origin "$(params.source-snapshot-prefix)/$revision"
git -C /workspace/source checkout --detach FETCH_HEAD
test "$(git -C /workspace/source rev-parse HEAD)" = "$revision"
rm -f "$askpass"
printf '{"ok":true,"phase":"source","sourceCommit":"%s","valuesPrinted":false}\n' "$revision"
`,
        securityContext: nonRootSecurity(),
        volumeMounts: [
          { name: "source-token", mountPath: "/var/run/pikaoa-source", readOnly: true },
        ],
      }],
      volumes: [{ name: "source-token", secret: { secretName: "$(params.gitops-secret-name)", items: [{ key: target.gitops.credentialTokenKey, path: "token" }] } }],
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "source-snapshot-prefix", value: "$(params.source-snapshot-prefix)" },
      { name: "git-read-url", value: "$(params.git-read-url)" },
      { name: "gitops-username", value: "$(params.gitops-username)" },
      { name: "gitops-secret-name", value: "$(params.gitops-secret-name)" },
    ],
    workspaces: [{ name: "workspace", workspace: "workspace" }],
  };
}

function imageBuildTask(target: PikaoaRuntimeSpec, component: "api" | "worker" | "web"): Record<string, unknown> {
  const taskName = `build-${component}`;
  const imageRepository = target.build.images[component];
  const dockerfile = target.build.dockerfiles[component];
  const cacheRef = target.build.cache.refs[component];
  return {
    name: taskName,
    runAfter: ["source"],
    taskSpec: {
      params: [{ name: "revision", type: "string" }],
      workspaces: [{ name: "workspace", mountPath: "/workspace" }],
      results: [{ name: "digest", type: "string" }, { name: "image", type: "string" }],
      steps: [{
        name: "build",
        image: target.ci.buildkitImage,
        imagePullPolicy: "IfNotPresent",
        workingDir: "/workspace/source",
        env: [{ name: "BUILDKITD_FLAGS", value: "--oci-worker-no-process-sandbox --oci-worker-net=host --allow-insecure-entitlement network.host" }],
        script: `#!/bin/sh
set -eu
revision="$(params.revision)"
tag=${shellSingleQuote(imageRepository)}:"$revision"
metadata=/tmp/${component}-metadata.json
set +e
buildctl-daemonless.sh build \\
  --frontend dockerfile.v0 \\
  --local context=. \\
  --local dockerfile=. \\
  --opt filename=${shellSingleQuote(dockerfile)} \\
  --opt network=${shellSingleQuote(target.build.networkMode)} \\
  --output "type=image,name=$tag,push=true" \\
  --import-cache ${shellSingleQuote(`type=${target.build.cache.mode},ref=${cacheRef}`)} \\
  --export-cache ${shellSingleQuote(`type=${target.build.cache.mode},ref=${cacheRef},mode=max,ignore-error=true`)} \\
  --metadata-file "$metadata"
build_status=$?
set -e
metadata_compact=
if [ -f "$metadata" ]; then
  metadata_compact=$(tr -d '\\n\\r' < "$metadata")
fi
digest=$(printf '%s' "$metadata_compact" | sed -n 's/.*"containerimage.digest"[[:space:]]*:[[:space:]]*"\\(sha256:[0-9a-f]\\{64\\}\\)".*/\\1/p' | head -n1)
if ! printf '%s' "$digest" | grep -Eq '^sha256:[0-9a-f]{64}$'; then
  registry_host=${shellSingleQuote(imageRepository.split("/")[0] ?? "")}
  registry_path=${shellSingleQuote(imageRepository.split("/").slice(1).join("/"))}
  headers=$(wget --server-response --spider --header='Accept: application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json' "http://$registry_host/v2/$registry_path/manifests/$revision" 2>&1 || true)
  digest=$(printf '%s\\n' "$headers" | awk 'BEGIN{IGNORECASE=1} /^[[:space:]]*Docker-Content-Digest:/ {gsub(/\\r/, "", $2); print $2; exit}')
fi
if ! printf '%s' "$digest" | grep -Eq '^sha256:[0-9a-f]{64}$'; then
  echo 'build digest missing from metadata and registry manifest' >&2
  exit 3
fi
if [ "$build_status" -ne 0 ]; then
  printf '{"level":"warning","code":"buildctl-nonzero-artifact-verified","component":"${component}","buildctlExitCode":%s,"artifactVerified":true,"blocking":false,"valuesPrinted":false}\\n' "$build_status" >&2
fi
printf '%s' "$digest" > "$(results.digest.path)"
printf '%s@%s' ${shellSingleQuote(imageRepository)} "$digest" > "$(results.image.path)"
printf '{"ok":true,"phase":"${taskName}","sourceCommit":"%s","imageTag":"%s","digest":"%s","valuesPrinted":false}\n' "$revision" "$tag" "$digest"
`,
        securityContext: { privileged: true, runAsUser: 1000, runAsGroup: 1000 },
      }],
    },
    params: [{ name: "revision", value: "$(params.revision)" }],
    workspaces: [{ name: "workspace", workspace: "workspace" }],
  };
}

function gitOpsTask(target: PikaoaRuntimeSpec, runtimeManifest: string): Record<string, unknown> {
  const manifestB64 = Buffer.from(runtimeManifest, "utf8").toString("base64");
  return {
    name: "gitops-publish",
    runAfter: ["build-api", "build-worker", "build-web"],
    taskSpec: {
      params: [
        { name: "revision", type: "string" },
        { name: "gitops-read-url", type: "string" },
        { name: "gitops-write-url", type: "string" },
        { name: "gitops-username", type: "string" },
        { name: "gitops-secret-name", type: "string" },
        { name: "api-image", type: "string" },
        { name: "worker-image", type: "string" },
        { name: "web-image", type: "string" },
      ],
      workspaces: [{ name: "workspace", mountPath: "/workspace" }],
      steps: [{
        name: "publish",
        image: target.ci.toolsImage,
        imagePullPolicy: "IfNotPresent",
        env: [{ name: "SOURCE_COMMIT", value: "$(params.revision)" }],
        script: `#!/bin/sh
set -eu
askpass=/tmp/pikaoa-git-askpass
cat >"$askpass" <<'ASKPASS'
#!/bin/sh
case "$1" in
  *Username*) printf '%s' "$PIKAOA_GIT_USERNAME" ;;
  *Password*) cat /var/run/pikaoa-gitops/token ;;
  *) exit 1 ;;
esac
ASKPASS
chmod 700 "$askpass"
export PIKAOA_GIT_USERNAME="$(params.gitops-username)"
export GIT_ASKPASS="$askpass"
export GIT_TERMINAL_PROMPT=0
case "$SOURCE_COMMIT" in *[!0-9a-f]*|'') echo 'source commit must be a full lowercase commit' >&2; exit 2;; esac
test "\${#SOURCE_COMMIT}" -eq 40
api_image="$(params.api-image)"
worker_image="$(params.worker-image)"
web_image="$(params.web-image)"
for image in "$api_image" "$worker_image" "$web_image"; do
  if ! printf '%s' "$image" | grep -Eq '@sha256:[0-9a-f]{64}$'; then
    echo 'required digestRef missing' >&2
    exit 4
  fi
done
rm -rf /workspace/gitops
mkdir -p /workspace/gitops
git -C /workspace/gitops init
git -C /workspace/gitops remote add origin "$(params.gitops-read-url)"
if git ls-remote --exit-code --heads "$(params.gitops-read-url)" ${shellSingleQuote(target.gitops.branch)} >/dev/null 2>&1; then
  git -C /workspace/gitops fetch --depth=1 origin ${shellSingleQuote(target.gitops.branch)}
  git -C /workspace/gitops checkout -B ${shellSingleQuote(target.gitops.branch)} FETCH_HEAD
else
  git -C /workspace/gitops checkout --orphan ${shellSingleQuote(target.gitops.branch)}
  git -C /workspace/gitops rm -rf . >/dev/null 2>&1 || true
fi
manifest=/workspace/gitops/${shellSingleQuote(target.gitops.manifestPath)}
mkdir -p "$(dirname "$manifest")"
printf '%s' ${shellSingleQuote(manifestB64)} | base64 -d > "$manifest"
sed -i \\
  -e "s|__PIKAOA_SOURCE_COMMIT__|$SOURCE_COMMIT|g" \\
  -e "s|__PIKAOA_API_IMAGE__|$(params.api-image)|g" \\
  -e "s|__PIKAOA_WORKER_IMAGE__|$(params.worker-image)|g" \\
  -e "s|__PIKAOA_WEB_IMAGE__|$(params.web-image)|g" \\
  "$manifest"
if grep -Eq '__PIKAOA_SOURCE_COMMIT__|__PIKAOA_(API|WORKER|WEB)_IMAGE__' "$manifest"; then
  echo 'GitOps manifest contains unresolved provenance or image placeholders' >&2
  exit 6
fi
git -C /workspace/gitops config user.name ${shellSingleQuote(target.gitops.authorName)}
git -C /workspace/gitops config user.email ${shellSingleQuote(target.gitops.authorEmail)}
git -C /workspace/gitops add -- ${shellSingleQuote(target.gitops.manifestPath)}
if git -C /workspace/gitops diff --cached --quiet; then
  changed=false
else
  git -C /workspace/gitops commit -m "chore(gitops): deploy pikaoa $SOURCE_COMMIT"
  git -C /workspace/gitops push "$(params.gitops-write-url)" HEAD:${shellSingleQuote(target.gitops.branch)}
  changed=true
fi
gitops_commit=$(git -C /workspace/gitops rev-parse HEAD)
case "$gitops_commit" in [0-9a-f][0-9a-f][0-9a-f][0-9a-f]*) ;; *) echo 'gitops commit missing' >&2; exit 5;; esac
rm -f "$askpass"
printf '{"ok":true,"status":"published","phase":"gitops-publish","sourceCommitId":"%s","registryVerified":true,"publishedCount":3,"reusedCount":0,"requiredServiceCount":3,"services":[{"service":"api","digestRef":"%s","digest":"%s"},{"service":"worker","digestRef":"%s","digest":"%s"},{"service":"web","digestRef":"%s","digest":"%s"}],"gitopsCommit":"%s","changed":%s,"valuesPrinted":false}\n' \
  "$SOURCE_COMMIT" "$api_image" "\${api_image##*@}" "$worker_image" "\${worker_image##*@}" "$web_image" "\${web_image##*@}" "$gitops_commit" "$changed"
`,
        securityContext: nonRootSecurity(),
        volumeMounts: [
          { name: "gitops-token", mountPath: "/var/run/pikaoa-gitops", readOnly: true },
        ],
      }],
      volumes: [{ name: "gitops-token", secret: { secretName: "$(params.gitops-secret-name)", items: [{ key: target.gitops.credentialTokenKey, path: "token" }] } }],
    },
    params: [
      { name: "revision", value: "$(params.revision)" },
      { name: "gitops-read-url", value: "$(params.gitops-read-url)" },
      { name: "gitops-write-url", value: "$(params.gitops-write-url)" },
      { name: "gitops-username", value: "$(params.gitops-username)" },
      { name: "gitops-secret-name", value: "$(params.gitops-secret-name)" },
      { name: "api-image", value: "$(tasks.build-api.results.image)" },
      { name: "worker-image", value: "$(tasks.build-worker.results.image)" },
      { name: "web-image", value: "$(tasks.build-web.results.image)" },
    ],
    workspaces: [{ name: "workspace", workspace: "workspace" }],
  };
}

function renderGitOpsManifest(target: PikaoaRuntimeSpec): string {
  const context: PikaoaRuntimeRenderContext = {
    instanceId: "default",
    commit: "__PIKAOA_SOURCE_COMMIT__",
    namespace: target.namespace,
    apiImage: "__PIKAOA_API_IMAGE__",
    workerImage: "__PIKAOA_WORKER_IMAGE__",
    webImage: "__PIKAOA_WEB_IMAGE__",
    initializerImage: "__PIKAOA_API_IMAGE__",
  };
  const manifest = renderPikaoaRuntimeManifest(target, context, { initializerHook: "argo-presync" });
  return manifest.map((object) => Bun.YAML.stringify(object, null, 2).trim()).join("\n---\n") + "\n";
}

function assertBinding(target: PikaoaRuntimeSpec, binding: PikaoaRendererBinding): void {
  const expected: Readonly<Record<string, string>> = {
    node: target.node,
    lane: target.ci.lane,
    namespace: target.ci.namespace,
    pipeline: target.ci.pipeline,
    pipelineRunPrefix: target.ci.pipelineRunPrefix,
    sourceBranch: target.source.branch,
    gitopsBranch: target.gitops.branch,
    serviceAccount: target.ci.serviceAccountName,
  };
  const actual: Readonly<Record<string, string | undefined>> = {
    node: binding.consumer.node,
    lane: binding.consumer.lane,
    namespace: binding.consumer.namespace,
    pipeline: binding.consumer.pipeline,
    pipelineRunPrefix: binding.consumer.pipelineRunPrefix,
    sourceBranch: binding.repository.params.source_branch,
    gitopsBranch: binding.repository.params.gitops_branch,
    serviceAccount: binding.repository.params.service_account,
  };
  for (const [key, value] of Object.entries(expected)) {
    if (actual[key] !== value) throw new Error(`PikaOA runtime binding ${key} must equal owning YAML value ${value}`);
  }
}

function assertSourceRepositoryContract(target: PikaoaRuntimeSpec, sourceWorktree: string): void {
  for (const path of Object.values(target.build.dockerfiles)) {
    if (!existsSync(resolve(sourceWorktree, path))) throw new Error(`PikaOA source worktree is missing ${path}`);
  }
}

function nonRootSecurity(): Record<string, unknown> {
  return { allowPrivilegeEscalation: false, runAsNonRoot: true, runAsUser: 1000, runAsGroup: 1000 };
}

function shellSingleQuote(value: string): string {
  return `'${value.replaceAll("'", `'"'"'`)}'`;
}
