import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import { mesh, parseEnvFromStack } from "@mesh-tech/infra-components";

// ============================================================================
// Configuration
// ============================================================================

const config = new pulumi.Config("mesh");

const tenant = config.require("tenant");
const env = parseEnvFromStack(tenant);

// Get AWS account ID
const callerIdentity = await aws.getCallerIdentity();
const awsAccountId = callerIdentity.accountId;

// ============================================================================
// Platform Infrastructure
// ============================================================================
// MeshPlatform:
// - Auto-imports core from SSM (use coreEnv config to override which env)
// - Creates Temporal, Zitadel, Monitoring (if configured)
// - Auto-exports to SSM: /mesh/{tenant}/{env}/platform

const meshPlatform = new mesh.layers.MeshPlatform("platform", {
  tenant,
  env,
  // Core environment to import from (defaults to env)
  // Set mesh:coreEnv in Pulumi config when core is deployed to a different stack
  coreEnv: config.get("coreEnv"),
  // Platform services - all disabled by default
  // Enable via Pulumi config: mesh:temporal, mesh:zitadel, mesh:spicedb, mesh:monitoring
  // infra-components >= 0.1.130 bundles the Temporal server source, so no
  // serverSourcePath override is needed — the SDK resolves its bundled copy.
  // Env-zone DNS (personal / secondary platform stacks): mesh:dns with a
  // public.parentZone makes every platform hostname derive from
  // {env}.{parentZone} instead of the shared core zone.
  dns: config.getObject("dns") ?? false,
  temporal: config.getObject("temporal") ?? false,
  zitadel: config.getObject("zitadel") ?? false,
  headscale: config.getObject("headscale") ?? false,
  subnetRouter: config.getObject("subnetRouter") ?? false,
  // Platform auth — org admin seeding (Zitadel users granted platform-wide
  // Temporal system admin). Config: mesh:auth: { orgAdmins: ["zitadel-id", ...] }
  // (SpiceDB authorization schemas are owned by apps/stacks, not the platform.)
  auth: config.getObject("auth") ?? false,
  monitoring: config.getObject("monitoring") ?? false,
  // Mesh Hub (operations dashboard) — tenant-opt-in via mesh:hub config.
  // Omit auth.clientId to have MeshHub auto-provision the Zitadel OIDC app
  // (requires mesh:zitadel + Temporal auth + public DNS, all enabled here).
  hub: config.getObject("hub") ?? false,
  // Database provisioner - enabled when RDS is available in core
  databaseProvisioner: config.getBoolean("databaseProvisioner") ?? true,
  // Cluster owner: controls whether cluster-scoped resources are created
  // Only ONE stack per cluster should be the owner (default: true)
  // Set mesh:clusterOwner: false for secondary stacks sharing the same EKS cluster
  clusterOwner: config.getBoolean("clusterOwner") ?? true,
  // Shared tenants that use this platform (creates per-tenant infra)
  // Config: mesh:tenants: { acme: {}, smallbank: { subdomain: sb } }
  tenants: config.getObject("tenants"),
  // Node pools for primary tenant workloads (e.g., Dagster jobs)
  // Config: mesh:primaryTenantNodePools: { dagster-jobs: { instanceType: t3.large } }
  primaryTenantNodePools: config.getObject("primaryTenantNodePools"),
  // Package registry (CodeArtifact) for distributing @mesh-tech/* packages
  // Config: mesh:packageRegistry: {} or mesh:packageRegistry: { readerRoleArns: [...] }
  // NOTE: no monorepoRoot here — package publishing stays with the
  // mesh-platform monorepo (scripts/publish-packages.sh). This stack only
  // provisions the CodeArtifact registry.
  packageRegistry: config.getObject("packageRegistry") ?? false,
  // DevBox - remote development instances (optional)
  // Config: mesh:devbox: { users: { <username>: { home: "/Users/<username>", ... } } }
  devbox: config.getObject("devbox") ?? false,
});

// ============================================================================
// Stack Exports
// ============================================================================
// These are available via `pulumi stack output`

export const stack = pulumi.getStack();
export const tenantName = tenant;
export const environment = env;
export const accountId = awsAccountId;

// All platform infrastructure outputs (includes core infra, services, ssmPath)
export const platform = meshPlatform.outputs;

// Tenant environments (primary + shared) - deployer roles, ingress config
// Note: Also exported to SSM at /mesh/{tenant}/{env}/app-tenants
export const tenantEnvironments = {
  primary: meshPlatform.tenantEnvironments.primaryTenant,
  shared: meshPlatform.tenantEnvironments.sharedTenants,
  ssmPath: meshPlatform.tenantEnvironments.ssmPath,
};
