/**
 * ShareBackend — the token-source seam for `agents artifacts share`.
 *
 * Two legitimate principals, picked once at publish time:
 *   - **managed**: the caller is signed in to Phoenix (`readSession()`), no
 *     explicit BYO override. Token is the Phoenix access_token; endpoint is
 *     the already-live `share.getrush.ai`. Zero Cloudflare setup.
 *   - **byo**: the existing static WRITE_TOKEN path (`readShareConfig()` +
 *     `readWriteToken()`). Unchanged for power users / custom domains / fleet
 *     injection of `SHARE_WRITE_TOKEN`.
 *
 * Dispatch is not a fallback: signed-in AND no BYO override → managed;
 * otherwise BYO. Fail loud when neither principal can authenticate.
 *
 * Explicit BYO override (any one is enough):
 *   - `opts.byo === true`
 *   - `opts.writeToken` (a caller-supplied static token, including tests)
 *   - `AGENTS_SHARE_BACKEND=byo`
 */
import { PHOENIX_ID_BASE, readSession } from '../identity/client.js';
import { selectStorageBackendKind } from '../storage/selection.js';
import { DEFAULT_SHARE_DOMAIN, LEGACY_MANAGED_SHARE_DOMAINS, readShareConfig, readWriteToken, readWriteTokenEnv, } from './config.js';
/** Env var that forces the BYO path. Value must be exactly `byo`. */
export const SHARE_BACKEND_ENV = 'AGENTS_SHARE_BACKEND';
/** URL-safe namespace: lowercase `[a-z0-9-]+`. Matches the Worker's sanitize.
 *
 * This is URL-safety, not collision-resistance: two values that differ only
 * in case or punctuation share a prefix. */
export function sanitizeShareNamespace(s) {
    return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
}
/**
 * Public managed-share handle from a verified email.
 *
 * `muqsitnawaz@gmail.com` → `muqsitnawaz`. Plus-tags are dropped
 * (`muqsitnawaz+dev@gmail.com` → `muqsitnawaz`) so the URL stays the
 * account's default name. Empty / missing email → `''` (caller falls
 * back to userId). Must match the Worker `handleFromEmail`.
 */
export function handleFromEmail(email) {
    if (!email)
        return '';
    const local = email.split('@')[0] ?? '';
    const beforePlus = local.split('+')[0] ?? local;
    return sanitizeShareNamespace(beforePlus);
}
/** Managed URL namespace: email handle, else sanitized userId (never empty if either is set). */
export function managedShareHandle(session) {
    return handleFromEmail(session.email) || sanitizeShareNamespace(session.userId ?? '');
}
export function managedShareBaseUrl() {
    return `https://${DEFAULT_SHARE_DOMAIN}`;
}
function shareEndpointHost(value) {
    return value.replace(/^https?:\/\//i, '').replace(/\/+$/, '').toLowerCase();
}
/**
 * True when this config is the platform managed endpoint (`share.getrush.ai`, or a
 * legacy alias — `share.agents-cli.sh` / `artifacts.prix.dev` — still bound to the
 * same Worker). The
 * deploy path uses this — not "the caller is signed in" — to decide whether to
 * bind `PHOENIX_ID_BASE` on the Worker.
 */
export function isManagedShareEndpoint(cfg) {
    const managedHosts = new Set([DEFAULT_SHARE_DOMAIN, ...LEGACY_MANAGED_SHARE_DOMAINS].map((h) => h.toLowerCase()));
    if (cfg.domain && managedHosts.has(shareEndpointHost(cfg.domain)))
        return true;
    if (cfg.baseUrl && managedHosts.has(shareEndpointHost(cfg.baseUrl)))
        return true;
    return false;
}
/**
 * Phoenix ID URL to bind on a managed Worker deploy. `undefined` for a
 * pure-BYO Worker (WRITE_TOKEN only). Fail loud if this is a managed deploy
 * but the base is empty — never skip-set a blank secret.
 */
export function phoenixIdBaseForDeploy(opts = {}, cfg) {
    const managed = opts.managed === true || (cfg != null && isManagedShareEndpoint(cfg));
    if (!managed)
        return undefined;
    const base = PHOENIX_ID_BASE.replace(/\/+$/, '').trim();
    if (!base) {
        throw new Error('Managed share deploy requires PHOENIX_ID_BASE so the Worker can verify Phoenix bearers. Set the PHOENIX_ID_BASE env var.');
    }
    return base;
}
/**
 * The share surface's BYO-override signals: an explicit `--byo`, a
 * caller-supplied static write token, or `AGENTS_SHARE_BACKEND=byo`. Detecting
 * WHICH signals count is surface-specific; the managed-vs-BYO decision itself is
 * the shared policy (`selectStorageBackendKind`). A persisted BYO endpoint config
 * is deliberately NOT an override here — a signed-in user with a stale BYO config
 * still publishes to managed unless they opt out explicitly (the product's
 * managed-first contract).
 */
function shareByoOverride(opts) {
    if (opts.byo === true)
        return true;
    if (opts.writeToken)
        return true;
    return (process.env[SHARE_BACKEND_ENV] ?? '').trim().toLowerCase() === 'byo';
}
/**
 * Pick the principal via the shared selection policy. Signed-in AND no explicit
 * BYO override → managed; otherwise BYO.
 */
export function shouldUseManaged(opts = {}) {
    return (selectStorageBackendKind({ byoOverride: shareByoOverride(opts), session: opts.session }) ===
        'managed');
}
export function resolveShareBackend(opts = {}) {
    if (shouldUseManaged(opts)) {
        const session = opts.session === undefined ? readSession() : opts.session;
        if (!session) {
            throw new Error("Not signed in. Run 'agents auth login'.");
        }
        return resolveManagedBackend(session);
    }
    return resolveByoBackend(opts);
}
function resolveManagedBackend(session) {
    if (!session.access_token) {
        throw new Error("Not signed in. Run 'agents auth login'.");
    }
    const namespace = managedShareHandle(session);
    if (!namespace) {
        throw new Error("Signed in but the session has no email or user id. Run 'agents auth login' again.");
    }
    return {
        kind: 'managed',
        baseUrl: managedShareBaseUrl(),
        token: session.access_token,
        namespace,
    };
}
function resolveByoBackend(opts) {
    const cfg = opts.config ?? readShareConfig();
    if (!cfg) {
        throw new Error("Not set up yet. Run 'agents auth login' to publish on the managed endpoint (zero Cloudflare setup), or 'agents artifacts setup' / 'agents artifacts share join' for your own Cloudflare.");
    }
    const token = opts.writeToken ??
        (opts.requireToken === false ? (readWriteTokenEnv() ?? '') : readWriteToken());
    // Namespace is the GitHub username. An explicit --github-user is sanitized
    // here; otherwise publish fills it via resolveShareUsername (gh/git config).
    const namespace = opts.githubUser ? sanitizeShareNamespace(opts.githubUser) : '';
    return {
        kind: 'byo',
        baseUrl: cfg.baseUrl.replace(/\/+$/, ''),
        token,
        namespace,
    };
}
