#!/usr/bin/env bash
set -euo pipefail

ROOT="$(git rev-parse --show-toplevel)"
APP_SLUG="${APP_SDK_SMOKE_APP_SLUG:-jupyterlab}"
MANIFEST_PATH="${APP_SDK_SMOKE_MANIFEST_PATH:-$ROOT/packages/products/appplatform/sdk/testdata/manifests/launchable-oci/${APP_SLUG}.json}"
OUT_DIR="${APP_SDK_SMOKE_OUT_DIR:-$ROOT/dist/app-sdk-smoke}"
OUT_FILE="$OUT_DIR/${APP_SLUG}-launch-connect-decommission.json"

mkdir -p "$OUT_DIR"

if [[ ! -f "$MANIFEST_PATH" ]]; then
  echo "ERROR: manifest not found: $MANIFEST_PATH" >&2
  exit 1
fi

go test ./packages/products/appplatform/sdk
go test ./pkg/sdk -run 'TestV3AppLaunchSubmit|TestAppsInstancesGet|TestAppsInstancesDecommission'

export APP_SLUG MANIFEST_PATH OUT_FILE
node <<'NODE'
const fs = require("node:fs");

const appSlug = process.env.APP_SLUG;
const manifestPath = process.env.MANIFEST_PATH;
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
const endpoints = ((manifest.network || {}).endpoints || []).map((endpoint) => ({
  name: endpoint.name,
  type: endpoint.type,
  auth_pattern: endpoint.auth_pattern,
  managed_ingress: endpoint.managed_ingress || null
}));
const connectEndpoints = ((manifest.outputs || {}).endpoints || []).map((endpoint) => endpoint.name);

if ((manifest.profile || {}).slug !== appSlug) {
  throw new Error(`manifest slug ${(manifest.profile || {}).slug} does not match ${appSlug}`);
}
if (connectEndpoints.length === 0) {
  throw new Error(`${appSlug} manifest has no SDK-visible connect endpoints`);
}

const evidence = {
  schema_version: "app-sdk-smoke.v1",
  app_slug: appSlug,
  manifest_path: manifestPath,
  generated_at: new Date().toISOString(),
  mode: "contract",
  evidence_result: "pass",
  proves_invariants: [
    "APP-CONTRACT-001",
    "APP-LAUNCH-001",
    "APP-CONNECT-001",
    "APP-DECOMMISSION-001"
  ],
  checks: [
    {
      id: "manifest_contract",
      result: "pass",
      command: "go test ./packages/products/appplatform/sdk",
      proves: ["manifest defaults", "routes", "resources", "validation"],
      invariants: ["APP-CONTRACT-001"]
    },
    {
      id: "sdk_launch",
      result: "pass",
      command: "go test ./pkg/sdk -run TestV3AppLaunchSubmit",
      endpoint: `/api/v1/launch/apps/${appSlug}`,
      proves: ["launch request", "project header", "idempotency key"],
      invariants: ["APP-LAUNCH-001"]
    },
    {
      id: "sdk_connect",
      result: "pass",
      command: "go test ./pkg/sdk -run TestAppsInstancesGet",
      endpoints: connectEndpoints,
      proves: ["app instance detail", "active proxy route discovery"],
      invariants: ["APP-CONNECT-001"]
    },
    {
      id: "sdk_decommission",
      result: "pass",
      command: "go test ./pkg/sdk -run TestAppsInstancesDecommission",
      endpoint: "/api/v1/projects/{project_id}/app-instances/{id}/decommission",
      proves: ["decommission request"],
      invariants: ["APP-DECOMMISSION-001"]
    }
  ],
  runtime_status: {
    mode: "contract_only",
    live_runtime_verified: false,
    follow_up: "PSS-VALIDATION-SECOND-PRODUCT-001 must attach live launch/connect/decommission evidence before L2 operational proof is complete."
  },
  failure_handling: {
    mode: "sdk_error_contract",
    live_failure_paths_verified: false,
    follow_up: "Add live app failure-contract evidence or Fairway follow-up before marking second-product validation complete."
  },
  manifest_summary: {
    display_name: manifest.profile.display_name,
    launch_mode: manifest.profile.launch_mode,
    artifact_name: manifest.artifacts.primary_image.artifact_name,
    endpoints
  }
};

fs.writeFileSync(process.env.OUT_FILE, `${JSON.stringify(evidence, null, 2)}\n`);
console.log(`OK: app SDK launch/connect/decommission smoke evidence written to ${process.env.OUT_FILE}`);
NODE
