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

if [[ ${EUID} -ne 0 ]]; then
  echo "run as root" >&2
  exit 1
fi

script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
install_root=/opt/guanghu/lake-lamp-authz
state_root=/var/lib/guanghu/architecture-provision
secret_root=/etc/guanghu/secrets/lake-lamp
authorization_env=$secret_root/authorization.env
provider_registry=/etc/guanghu/secrets/hololake-ai-providers.json
knowledge_repo=/var/lib/guanghu/personas/guanghu/hlcc-v16.0.1/data/repositories/bingshuo/hololake-knowledge-base.git
ghdr_authorizer_key=/var/lib/guanghu/lake-lamp-authz/ghdr-authorizer-private.pem
stamp=$(date -u +%Y%m%dT%H%M%SZ)
backup_root=$state_root/manual-backups/lake-lamp-authz-$stamp

required_source_files=(
  server.js
  workorder-manager.js
  map-gate.js
  smtp-mailer.js
  action-client.js
  architecture-provision-broker.js
  deployment-event.js
  deployment-event-worker.js
  deployment-source-policy.js
  guanghu-router.js
  repo-push-broker.js
  hololake-session.js
  hololake-capabilities.js
  ghdr-authorizer.js
  ghdr-controller-broker.js
  ghdr-controllers.json
)

for file in "${required_source_files[@]}" lake-lamp-authz.service lake-lamp-architecture-provision.service lake-lamp-deployment-event-worker.service; do
  [[ -f "$script_dir/$file" ]] || {
    echo "missing required release file: $file" >&2
    exit 1
  }
done
[[ -f "$script_dir/navigation-maps/GH-CVM-MAIN-PROD-01.json" ]] || {
  echo "missing required GHDR navigation map" >&2
  exit 1
}

install -d -m 0700 "$backup_root"
[[ ! -e "$install_root" ]] || cp -a "$install_root" "$backup_root/install-root"
for existing in \
  /etc/systemd/system/lake-lamp-authz.service \
  /etc/systemd/system/lake-lamp-architecture-provision.service \
  /etc/systemd/system/lake-lamp-deployment-event-worker.service \
  "$authorization_env" \
  "$provider_registry" \
  "$ghdr_authorizer_key"; do
  if [[ -e "$existing" ]]; then
    destination=$backup_root/existing${existing}
    install -d -m 0700 "$(dirname "$destination")"
    cp -a "$existing" "$destination"
  fi
done

rollback() {
  set +e
  if [[ -d "$backup_root/install-root" ]]; then
    rm -rf -- "$install_root"
    cp -a "$backup_root/install-root" "$install_root"
  fi
  for existing in \
    /etc/systemd/system/lake-lamp-authz.service \
    /etc/systemd/system/lake-lamp-architecture-provision.service \
    /etc/systemd/system/lake-lamp-deployment-event-worker.service \
    "$authorization_env" \
    "$provider_registry" \
    "$ghdr_authorizer_key"; do
    saved=$backup_root/existing${existing}
    if [[ -e "$saved" ]]; then
      install -d -m 0755 "$(dirname "$existing")"
      cp -a "$saved" "$existing"
    elif [[ "$existing" = "$provider_registry" || "$existing" = "$ghdr_authorizer_key" ]]; then
      rm -f -- "$existing"
    fi
  done
  systemctl daemon-reload
  systemctl restart lake-lamp-authz.service
  systemctl restart lake-lamp-architecture-provision.service
  systemctl restart lake-lamp-deployment-event-worker.service
}
trap 'rc=$?; if [[ $rc -ne 0 ]]; then rollback; fi; exit "$rc"' EXIT

install -d -m 0755 "$install_root"
for file in "${required_source_files[@]}"; do
  install -m 0644 "$script_dir/$file" "$install_root/$file"
done
install -d -m 0755 "$install_root/navigation-maps"
install -m 0644 \
  "$script_dir/navigation-maps/GH-CVM-MAIN-PROD-01.json" \
  "$install_root/navigation-maps/GH-CVM-MAIN-PROD-01.json"
install -m 0644 "$script_dir/lake-lamp-authz.service" /etc/systemd/system/lake-lamp-authz.service
install -m 0644 "$script_dir/lake-lamp-architecture-provision.service" /etc/systemd/system/lake-lamp-architecture-provision.service
install -m 0644 "$script_dir/lake-lamp-deployment-event-worker.service" /etc/systemd/system/lake-lamp-deployment-event-worker.service
install -d -m 0700 "$state_root"
install -d -m 0750 /var/lib/guanghu/deployment-events
install -d -m 0700 /var/lib/guanghu/deployment-events/receipts
install -d -m 0755 /opt/guanghu/architecture-releases
install -d -m 0755 /etc/guanghu/lake-lamp
install -d -m 0750 "$secret_root"
if [[ ! -e /etc/guanghu/lake-lamp/deployment-repositories.json ]]; then
  install -m 0644 "$script_dir/deployment-repositories.example.json" /etc/guanghu/lake-lamp/deployment-repositories.json
fi

[[ -f "$authorization_env" ]] || {
  echo "private authorization environment is missing" >&2
  exit 1
}

append_setting() {
  local key=$1
  local value=$2
  if ! grep -q "^${key}=" "$authorization_env"; then
    printf '%s=%s\n' "$key" "$value" >>"$authorization_env"
  fi
}

if ! grep -q '^HOLOLAKE_SESSION_PEPPER=' "$authorization_env"; then
  append_setting HOLOLAKE_SESSION_PEPPER "$(/usr/bin/openssl rand -hex 32)"
fi
append_setting HOLOLAKE_SESSION_STATE_FILE /var/lib/guanghu/lake-lamp-authz/hololake-sessions.json
append_setting HOLOLAKE_OTP_TTL 600
append_setting HOLOLAKE_ACCOUNT_SESSION_TTL 86400
append_setting HOLOLAKE_OTP_REQUEST_LIMIT 6
append_setting HOLOLAKE_KNOWLEDGE_REPOSITORY_PATH "$knowledge_repo"
append_setting HOLOLAKE_KNOWLEDGE_MAX_ARCHIVE_BYTES 134217728
append_setting HOLOLAKE_AI_PROVIDERS_FILE "$provider_registry"
chmod 0600 "$authorization_env"

if [[ ! -f "$provider_registry" ]]; then
  /usr/bin/python3 - "$provider_registry" <<'PY'
import json
import pathlib
import sys

destination = pathlib.Path(sys.argv[1])
values = {}
roots = (
    pathlib.Path("/etc/guanghu/secrets"),
    pathlib.Path("/etc/guanghu/persona-secrets"),
)
for root in roots:
    if not root.exists():
        continue
    for file in root.rglob("*.env"):
        try:
            for raw in file.read_text().splitlines():
                line = raw.strip()
                if not line or line.startswith("#") or "=" not in line:
                    continue
                key, value = line.split("=", 1)
                values.setdefault(key.strip(), value.strip().strip("'\""))
        except (OSError, UnicodeError):
            continue

providers = {}
if values.get("DEEPSEEK_API_KEY"):
    providers["deepseek"] = {
        "name": "DeepSeek",
        "base_url": "https://api.deepseek.com",
        "api_key": values["DEEPSEEK_API_KEY"],
        "models": ["deepseek-chat", "deepseek-reasoner"],
    }
elif values.get("OPENAI_API_KEY"):
    providers["openai"] = {
        "name": "OpenAI",
        "base_url": "https://api.openai.com/v1",
        "api_key": values["OPENAI_API_KEY"],
        "models": ["gpt-4.1-mini"],
    }
elif values.get("DASHSCOPE_API_KEY"):
    providers["qwen"] = {
        "name": "Qwen",
        "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
        "api_key": values["DASHSCOPE_API_KEY"],
        "models": ["qwen-plus"],
    }

if providers:
    destination.parent.mkdir(parents=True, exist_ok=True)
    temporary = destination.with_suffix(".tmp")
    temporary.write_text(json.dumps({
        "schema": "guanghu.hololake-ai-providers/v1",
        "providers": providers,
    }, ensure_ascii=False, indent=2) + "\n")
    temporary.chmod(0o640)
    temporary.replace(destination)
PY
fi

if [[ -f "$provider_registry" ]]; then
  chown root:guanghu-authz "$provider_registry"
  chmod 0640 "$provider_registry"
fi

[[ -d "$knowledge_repo" ]] || {
  echo "registered HoloLake knowledge repository is missing" >&2
  exit 1
}
command -v setfacl >/dev/null 2>&1 || {
  echo "setfacl is required for private knowledge repository access" >&2
  exit 1
}
setfacl -R -m u:guanghu-authz:rX "$knowledge_repo"
setfacl -R -d -m u:guanghu-authz:rX "$knowledge_repo"
runuser -u guanghu-authz -- git --git-dir="$knowledge_repo" rev-parse --verify refs/heads/main >/dev/null

systemctl daemon-reload
systemctl enable --now lake-lamp-architecture-provision.service
systemctl restart lake-lamp-authz.service
systemctl enable --now lake-lamp-deployment-event-worker.service
systemctl is-active --quiet lake-lamp-architecture-provision.service
systemctl is-active --quiet lake-lamp-authz.service
systemctl is-active --quiet lake-lamp-deployment-event-worker.service
health=$(/usr/bin/curl -fsS --max-time 10 http://127.0.0.1:3921/health)
/usr/bin/node -e '
const health = JSON.parse(process.argv[1]);
if (!health.ok || health.service !== "lake-lamp-authz") process.exit(1);
if (!health.hololake_mobile || !health.hololake_mobile.email_session || !health.hololake_mobile.knowledge_snapshot) process.exit(1);
' "$health"
if [[ -f "$provider_registry" ]]; then
  /usr/bin/node -e '
const health = JSON.parse(process.argv[1]);
if (!health.hololake_mobile || !health.hololake_mobile.ai_gateway) process.exit(1);
' "$health"
fi
ghdr_public=$(/usr/bin/curl -fsS --max-time 10 http://127.0.0.1:3921/api/ghdr/authorizer-public-key)
/usr/bin/node -e '
const response = JSON.parse(process.argv[1]);
const binding = response && response.binding;
if (!response.ok || !binding || binding.algorithm !== "Ed25519") process.exit(1);
if (!/^[-A-Za-z0-9+/=\r\n ]*PUBLIC KEY[-A-Za-z0-9+/=\r\n ]*$/.test(binding.public_key_pem)) process.exit(1);
if (!/^[0-9a-f]{64}$/.test(binding.public_key_sha256)) process.exit(1);
if (/PRIVATE KEY/.test(JSON.stringify(response))) process.exit(1);
' "$ghdr_public"
[[ -f "$ghdr_authorizer_key" && ! -L "$ghdr_authorizer_key" ]]
[[ $(stat -c '%a' "$ghdr_authorizer_key") = 600 ]]
trap - EXIT
printf 'HOLOLAKE_MOBILE_AND_GHDR_CAPABILITIES_INSTALLED backup=%s\n' "$backup_root"
