"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.archPilotCloudUrlEnvironmentVariable = exports.defaultArchPilotCloudAppBaseUrl = exports.defaultArchPilotCloudServerUrl = void 0;
exports.resolveArchPilotCloudServer = resolveArchPilotCloudServer;
exports.validateCloudConnection = validateCloudConnection;
exports.defaultArchPilotCloudServerUrl = 'https://api.archpilot.org';
exports.defaultArchPilotCloudAppBaseUrl = 'https://archpilot.org/app';
exports.archPilotCloudUrlEnvironmentVariable = 'ARCHPILOT_CLOUD_URL';
function normalizeCloudServerUrl(serverUrl) {
    const trimmed = serverUrl.trim();
    if (trimmed.length === 0) {
        throw new Error('Cloud URL is required.');
    }
    let parsed;
    try {
        parsed = new URL(trimmed);
    }
    catch {
        throw new Error('Cloud URL is invalid. Use an absolute URL.');
    }
    if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
        throw new Error('Cloud URL must use http or https.');
    }
    const normalized = parsed.toString().replace(/\/$/u, '');
    const normalizedPath = parsed.pathname.replace(/\/+$/u, '');
    if (normalizedPath.endsWith('/api/v1')) {
        throw new Error('Enter the ArchPilot Cloud API base URL, for example https://api.archpilot.org or http://localhost:4000. Do not include /api/v1.');
    }
    return normalized;
}
function resolveArchPilotAppBaseUrl(apiBaseUrl, explicitAppBaseUrl) {
    if (explicitAppBaseUrl?.trim()) {
        return normalizeCloudServerUrl(explicitAppBaseUrl);
    }
    const parsedApiBaseUrl = new URL(apiBaseUrl);
    if (parsedApiBaseUrl.hostname === 'api.archpilot.org') {
        return exports.defaultArchPilotCloudAppBaseUrl;
    }
    if (parsedApiBaseUrl.port === '4000' &&
        (parsedApiBaseUrl.hostname === 'localhost' ||
            parsedApiBaseUrl.hostname === '127.0.0.1' ||
            parsedApiBaseUrl.hostname === '::1')) {
        const appBaseUrl = new URL(parsedApiBaseUrl.toString());
        appBaseUrl.port = '3000';
        appBaseUrl.pathname = '/app';
        appBaseUrl.search = '';
        appBaseUrl.hash = '';
        return appBaseUrl.toString().replace(/\/$/u, '');
    }
    return exports.defaultArchPilotCloudAppBaseUrl;
}
function resolveArchPilotCloudServer(input) {
    const explicit = input?.explicitApiBaseUrl?.trim() || input?.explicitServerUrl?.trim();
    const environment = input?.environment ?? process.env;
    const environmentUrl = environment.ARCHPILOT_CLOUD_URL?.trim();
    const source = explicit
        ? 'explicit'
        : environmentUrl
            ? 'environment'
            : 'production';
    const apiBaseUrl = normalizeCloudServerUrl(explicit || environmentUrl || exports.defaultArchPilotCloudServerUrl);
    const parsed = new URL(apiBaseUrl);
    const local = parsed.hostname === 'localhost' ||
        parsed.hostname === '127.0.0.1' ||
        parsed.hostname === '::1';
    return {
        apiBaseUrl,
        appBaseUrl: resolveArchPilotAppBaseUrl(apiBaseUrl, input?.explicitAppBaseUrl),
        serverUrl: apiBaseUrl,
        source,
        local,
    };
}
function resolveCloudConnectionEndpoint(serverUrl) {
    const base = new URL(normalizeCloudServerUrl(serverUrl));
    return new URL('/api/v1/auth/validate', base).toString();
}
function parseCloudResponse(raw) {
    if (raw.trim().length === 0) {
        return {};
    }
    try {
        return JSON.parse(raw);
    }
    catch {
        return { message: raw };
    }
}
function readString(record, keys) {
    for (const key of keys) {
        const value = record[key];
        if (typeof value === 'string' && value.trim().length > 0) {
            return value.trim();
        }
    }
    return undefined;
}
function readNestedRecord(record, keys) {
    for (const key of keys) {
        const value = record[key];
        if (value && typeof value === 'object' && !Array.isArray(value)) {
            return value;
        }
    }
    return undefined;
}
function extractOrganizationMetadata(parsed) {
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
        return {};
    }
    const record = parsed;
    const direct = readString(record, ['organization', 'organizationName', 'org', 'orgName']);
    const organizationRecord = readNestedRecord(record, ['organization', 'org']);
    const organizationName = readString(record, ['organizationName', 'orgName']) ??
        (organizationRecord ? readString(organizationRecord, ['name', 'displayName']) : undefined);
    const organizationSlug = readString(record, ['organizationSlug', 'orgSlug']) ??
        (organizationRecord ? readString(organizationRecord, ['slug', 'id']) : undefined);
    const organization = direct ?? organizationName ?? organizationSlug;
    return {
        ...(organization ? { organization } : {}),
        ...(organizationName ? { organizationName } : {}),
        ...(organizationSlug ? { organizationSlug } : {}),
    };
}
function extractPlanName(parsed) {
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
        return undefined;
    }
    const record = parsed;
    const direct = readString(record, ['planName', 'plan']);
    if (direct) {
        return direct;
    }
    const plan = readNestedRecord(record, ['plan', 'subscription']);
    return plan ? readString(plan, ['name', 'label', 'slug', 'id']) : undefined;
}
function extractTokenMetadata(parsed) {
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
        return {};
    }
    const record = parsed;
    const tokenRecord = readNestedRecord(record, ['token', 'tokenMetadata', 'apiToken']);
    const tokenLabel = readString(record, ['tokenLabel', 'tokenName']) ??
        (tokenRecord ? readString(tokenRecord, ['label', 'name']) : undefined);
    const tokenLast4 = readString(record, ['tokenLast4', 'last4']) ??
        (tokenRecord ? readString(tokenRecord, ['last4', 'tokenLast4']) : undefined);
    return {
        ...(tokenLabel ? { tokenLabel } : {}),
        ...(tokenLast4 ? { tokenLast4 } : {}),
    };
}
function extractErrorMessage(parsed) {
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
        return '';
    }
    const record = parsed;
    return readString(record, ['message', 'error']) ?? '';
}
async function validateCloudConnection(input) {
    const endpoint = resolveCloudConnectionEndpoint(input.serverUrl);
    const token = input.token.trim();
    if (token.length === 0) {
        throw new Error('API token is required.');
    }
    const timeoutMs = input.timeoutMs ?? 10000;
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), timeoutMs);
    try {
        const response = await fetch(endpoint, {
            method: 'GET',
            headers: {
                accept: 'application/json',
                authorization: `Bearer ${token}`,
            },
            signal: controller.signal,
        });
        const parsed = parseCloudResponse(await response.text());
        if (!response.ok) {
            const detail = extractErrorMessage(parsed);
            throw new Error(`Cloud connection validation failed with status ${response.status}.${detail ? ` ${detail}` : ''}`);
        }
        const organization = extractOrganizationMetadata(parsed);
        const planName = extractPlanName(parsed);
        const tokenMetadata = extractTokenMetadata(parsed);
        return {
            serverUrl: input.serverUrl.trim(),
            ...organization,
            ...(planName ? { planName } : {}),
            ...tokenMetadata,
            validatedAt: new Date().toISOString(),
        };
    }
    catch (error) {
        if (error instanceof DOMException && error.name === 'AbortError') {
            throw new Error(`Cloud connection validation timed out after ${timeoutMs}ms.`);
        }
        throw error;
    }
    finally {
        clearTimeout(timeout);
    }
}
//# sourceMappingURL=cloudConnection.js.map