#!/bin/bash
###############################################################################
# Smarter Visitor Registration - Prepare the Microsoft Entra app registration
###############################################################################
# Creates (or updates) the app registration that the application uses for
# browser, Outlook and Teams sign-in, and prints its client ID. Run it BEFORE
# deploying from the Azure Marketplace or the Azure portal: those deployment
# paths cannot create Entra resources themselves (Microsoft Graph Bicep
# resources are only supported from Azure CLI/PowerShell deployments).
#
# Usage: ./prepare-app-registration.sh <web-app-name> [deployment-prefix]
#
# Example:
#   ./prepare-app-registration.sh contoso-visitor-registration visitorreg
#
# Requirements: Azure CLI, signed in (az login) with a Microsoft Entra account
# that may create app registrations (Application Administrator or
# Cloud Application Administrator). Nothing is deployed to Azure.
#
# The configuration mirrors infrastructure/bicep/modules/appRegistration.bicep.
###############################################################################

set -euo pipefail

WEBAPP_NAME="${1:-}"
DEPLOYMENT_NAME="${2:-visitorreg}"

if [ -z "$WEBAPP_NAME" ]; then
    echo "Usage: $0 <web-app-name> [deployment-prefix]" >&2
    echo "  web-app-name       the globally unique web app name you will enter in the deployment (becomes <name>.azurewebsites.net)" >&2
    echo "  deployment-prefix  the deployment prefix you will enter in the deployment (default: visitorreg)" >&2
    exit 1
fi

if ! command -v az > /dev/null 2>&1; then
    echo "Azure CLI not found. Install: https://learn.microsoft.com/cli/azure/install-azure-cli" >&2
    exit 1
fi
if ! az account show > /dev/null 2>&1; then
    az login > /dev/null
fi

GRAPH="https://graph.microsoft.com/v1.0"
HOSTNAME="${WEBAPP_NAME}.azurewebsites.net"
DISPLAY_NAME="Visitor Registration ${DEPLOYMENT_NAME}"
SCOPE_ID="858a0190-b686-5d8d-9b74-18037cc197a7"   # access_as_user, fixed across deployments
TENANT_ID=$(az account show --query tenantId -o tsv)

echo "Tenant:         ${TENANT_ID}"
echo "Display name:   ${DISPLAY_NAME}"
echo "Web app host:   ${HOSTNAME}"
echo ""

# Definition without the fields that need the generated application ID.
read -r -d '' APP_BODY <<JSON || true
{
  "displayName": "${DISPLAY_NAME}",
  "signInAudience": "AzureADMyOrg",
  "groupMembershipClaims": "SecurityGroup",
  "tags": ["Application:Smarter Visitor Registration", "ManagedBy:prepare-app-registration"],
  "requiredResourceAccess": [
    {
      "resourceAppId": "00000003-0000-0000-c000-000000000000",
      "resourceAccess": [
        { "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", "type": "Scope" },
        { "id": "b340eb25-3456-403f-be2f-af7a0d370277", "type": "Scope" },
        { "id": "5f8c59db-677d-491f-a6b8-5f174b11ec1d", "type": "Scope" },
        { "id": "ba47897c-39ec-4d83-8086-ee8256fa737d", "type": "Scope" },
        { "id": "e383f46e-2787-4529-855e-0e479a3ffac0", "type": "Scope" }
      ]
    }
  ],
  "api": {
    "requestedAccessTokenVersion": 2,
    "oauth2PermissionScopes": [
      {
        "id": "${SCOPE_ID}",
        "value": "access_as_user",
        "type": "User",
        "isEnabled": true,
        "adminConsentDisplayName": "Access visitor events API",
        "adminConsentDescription": "Allow Outlook Add-in to access visitor event API on behalf of the user",
        "userConsentDisplayName": "Create visitor events",
        "userConsentDescription": "Allow the add-in to create visitor events on your behalf"
      }
    ]
  },
  "spa": {
    "redirectUris": [
      "https://${HOSTNAME}/auth/callback",
      "http://localhost:5173/auth/callback",
      "https://localhost:5173/auth/callback",
      "http://localhost:3000/auth/callback",
      "https://localhost:3000/auth/callback"
    ]
  },
  "web": {
    "redirectUris": [
      "https://${HOSTNAME}/.auth/login/aad/callback",
      "http://localhost:3000/.auth/login/aad/callback",
      "https://outlook.office.com/connectors",
      "https://outlook.office365.com/connectors",
      "https://outlook-sdf.office.com/connectors"
    ],
    "implicitGrantSettings": { "enableIdTokenIssuance": true, "enableAccessTokenIssuance": true }
  }
}
JSON

# Reuse an existing registration with the same display name (re-runs are safe).
EXISTING=$(az rest --method GET --uri "${GRAPH}/applications?\$filter=displayName eq '${DISPLAY_NAME// /%20}'&\$select=id,appId" --query "value[0]" -o json 2>/dev/null || echo "null")
if [ "$EXISTING" != "null" ] && [ -n "$EXISTING" ]; then
    OBJECT_ID=$(echo "$EXISTING" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
    APP_ID=$(echo "$EXISTING" | python3 -c 'import json,sys; print(json.load(sys.stdin)["appId"])')
    echo "Updating existing app registration ${APP_ID} ..."
    az rest --method PATCH --uri "${GRAPH}/applications/${OBJECT_ID}" --headers "Content-Type=application/json" --body "$APP_BODY" --output none
else
    echo "Creating app registration ..."
    CREATED=$(az rest --method POST --uri "${GRAPH}/applications" --headers "Content-Type=application/json" --body "$APP_BODY" -o json)
    OBJECT_ID=$(echo "$CREATED" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
    APP_ID=$(echo "$CREATED" | python3 -c 'import json,sys; print(json.load(sys.stdin)["appId"])')
fi

# Fields that depend on the application ID: identifier URI and Office/Teams pre-authorization.
read -r -d '' FINALIZE_BODY <<JSON || true
{
  "identifierUris": ["api://${HOSTNAME}/${APP_ID}"],
  "api": {
    "preAuthorizedApplications": [
      { "appId": "ea5a67f6-b6f3-4338-b240-c655ddc3cc8e", "delegatedPermissionIds": ["${SCOPE_ID}"] },
      { "appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3", "delegatedPermissionIds": ["${SCOPE_ID}"] },
      { "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", "delegatedPermissionIds": ["${SCOPE_ID}"] },
      { "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", "delegatedPermissionIds": ["${SCOPE_ID}"] }
    ]
  }
}
JSON
# Graph needs a moment before the new object accepts updates.
for attempt in 1 2 3 4 5 6; do
    if az rest --method PATCH --uri "${GRAPH}/applications/${OBJECT_ID}" --headers "Content-Type=application/json" --body "$FINALIZE_BODY" --output none 2>/dev/null; then
        break
    fi
    if [ "$attempt" = 6 ]; then
        echo "Could not set identifier URI and pre-authorized clients. Run the script again in a minute." >&2
        exit 1
    fi
    sleep 10
done

# Service principal (enterprise application) in this tenant
if ! az ad sp show --id "$APP_ID" > /dev/null 2>&1; then
    az ad sp create --id "$APP_ID" --output none
fi

echo ""
echo "============================================================"
echo " App registration ready"
echo "============================================================"
echo "Client ID:       ${APP_ID}"
echo "Tenant ID:       ${TENANT_ID}"
echo "Identifier URI:  api://${HOSTNAME}/${APP_ID}"
echo ""
echo "Next steps:"
echo "1. Deploy Smarter Visitor Registration (Azure Marketplace or template) and enter"
echo "   the client ID above in the field 'Microsoft Entra application client ID'."
echo "   Use the same web app name (${WEBAPP_NAME}) in the deployment."
echo "2. After the deployment run grant-graph-permissions.sh to assign the Microsoft"
echo "   Graph application roles to the managed identity and to grant admin consent."
