/**
 * {{titleCase name}} — Pulumi app definition
 *
 * Pattern: getConfig → AppEnvironment → primitives → services → register
 */

import * as pulumi from "@pulumi/pulumi";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { mesh } from "@mesh-tech/app-kit/infra";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { tenant, platform, stack, deploy } = mesh.apps.getConfig(pulumi);
{{#if temporal}}

const TASK_QUEUE = "{{name}}";
{{/if}}

// =============================================================================
// Environment
// =============================================================================

const env = new mesh.apps.AppEnvironment("env", {
  tenant,
  platform,
  stack,
  deploy,
  appName: "{{name}}",
  namespace: true,
  rootDir: __dirname,
{{#if temporal}}
  temporal: {
    codecServer: {
      ingressSubdomain: "codec-{{name}}",
    },
  },
{{/if}}
});

// =============================================================================
// Primitives
// =============================================================================
{{#if database}}

const db = new mesh.apps.Database("db", { env });
{{/if}}
{{#if bucket}}

const uploads = new mesh.apps.Bucket("uploads", {
  env,
  forceDestroy: stack !== "prod",
});
{{/if}}

// =============================================================================
// Services
// =============================================================================
{{#if service}}

const api = new mesh.apps.Service("api", {
  env,
  title: "{{titleCase name}} API",
  description: "HTTP API for {{titleCase name}}",
  runtime: "node",
  src: "./api",
  port: 3000,
  link: [
{{#if database}}
    db.link({ environmentPrefix: "DATABASE" }),
{{/if}}
{{#if bucket}}
    uploads.link({ environmentPrefix: "UPLOADS", access: "readWrite" }),
{{/if}}
{{#if temporal}}
    env.temporal!.link({ environmentPrefix: "TEMPORAL", taskQueue: TASK_QUEUE }),
{{/if}}
  ],
  ingress: env.buildIngress({
    subdomain: "{{name}}",
    healthCheckPath: "/health",
  }),
  healthCheck: "/health",
  replicas: deploy ? 2 : 1,
  resources: { cpu: "100m", memory: "128Mi" },
});
{{/if}}
{{#if temporal}}

const worker = new mesh.apps.TemporalWorker("worker", {
  env,
  title: "{{titleCase name}} Worker",
  description: "Temporal workflow worker for {{titleCase name}}",
  runtime: "node",
  src: "./worker",
  taskQueue: TASK_QUEUE,
  replicas: 1,
  resources: { cpu: "100m", memory: "256Mi" },
});
{{/if}}

{{#if service}}

// =============================================================================
// Docs — the API's reference site, built by the platform from the spec and
// the guides in docs/pages/. In-cluster and under `mesh dev` only: no
// ingress, so nothing is published on a hostname until you choose to. To
// publish it, give it an ingress AND the platform sign-in (`auth: { provider:
// "mesh", clientId, clientSecret }` from a ZitadelAppIdentity application),
// then list it in the Hub with `env.register({ docs: { url: docs.url,
// provider: "zudoku" } })`. An API surface (`mesh.apps.ApiSurface`) declares
// the same site on its `docs` block and wires all of that itself.
// =============================================================================

new mesh.apps.ApiDocs("docs", {
  env,
  sources: { openapi: "./api/openapi.json" },
  pages: "./docs/pages",
  serverUrl: api.url,
  zudoku: {
    metadata: {
      title: "{{titleCase name}} API",
      description: "HTTP API for {{titleCase name}}",
    },
  },
});
{{/if}}

// =============================================================================
// Outputs
// =============================================================================

export const app = env.register({
  description: "{{titleCase name}}",
});

// Exported so the bindings above are used, and because a stack's URLs are the
// first thing anyone wants after a deploy. `pulumi stack output` prints them.
{{#if service}}
export const apiUrl = api.url;
{{/if}}
{{#if temporal}}
export const workerTaskQueue = worker.taskQueue;
{{/if}}
