import { StreamStorageService, TaskStorageService } from '@agentuity/core';
import { projectGet, sandboxResolve, deploymentGet, getWebhook, createServerFetchAdapter, getServiceUrls, } from '@agentuity/server';
import { getResourceInfo, setResourceInfo } from '../../cache';
import { getDefaultRegion } from '../../config';
import * as tui from '../../tui';
import { ErrorCode } from '../../errors';
/**
 * Determine the type of identifier based on its prefix
 */
export function getIdentifierType(identifier) {
    if (identifier.startsWith('proj_')) {
        return 'project';
    }
    if (identifier.startsWith('deploy_')) {
        return 'deployment';
    }
    if (identifier.startsWith('sbx_')) {
        return 'sandbox';
    }
    if (identifier.startsWith('task_')) {
        return 'task';
    }
    if (identifier.startsWith('stream_')) {
        return 'stream';
    }
    if (identifier.startsWith('wh_')) {
        return 'webhook';
    }
    // Default to project for unknown prefixes
    return 'project';
}
/**
 * Look up the region for a project, deployment, sandbox, or stream identifier.
 * Uses cache-first strategy with API fallback.
 *
 * @param apiClient - Required for project/deployment lookups, optional for sandbox/stream
 *                    (they create their own clients internally)
 */
export async function getIdentifierRegion(logger, auth, apiClient, profileName = 'production', identifier, orgId, config) {
    const identifierType = getIdentifierType(identifier);
    // For project, deployment, and sandbox, check cache first
    const cachedInfo = await getResourceInfo(identifierType, profileName, identifier);
    if (cachedInfo?.region) {
        logger.trace(`[region-lookup] Found cached region for ${identifier}: ${cachedInfo.region}`);
        return cachedInfo.region;
    }
    logger.trace(`[region-lookup] Cache miss for ${identifier}, fetching from API`);
    let region = null;
    if (identifierType === 'project') {
        if (!apiClient) {
            tui.fatal(`API client required for project region lookup. This is an internal error.`, ErrorCode.INVALID_ARGUMENT);
        }
        const project = await projectGet(apiClient, { id: identifier, mask: true, keys: false });
        region = project.cloudRegion ?? null;
    }
    else if (identifierType === 'deployment') {
        if (!apiClient) {
            tui.fatal(`API client required for deployment region lookup. This is an internal error.`, ErrorCode.INVALID_ARGUMENT);
        }
        const deployment = await deploymentGet(apiClient, identifier);
        region = deployment.cloudRegion ?? null;
    }
    else if (identifierType === 'task') {
        // Tasks live in per-tenant DBs accessible from any regional Catalyst.
        // Use default region to reach Catalyst, which can resolve the task for the org.
        const taskDefaultRegion = await getDefaultRegion(profileName, config);
        const taskBaseUrl = getServiceUrls(taskDefaultRegion).catalyst;
        const resolvedTaskOrgId = orgId ?? process.env.AGENTUITY_CLOUD_ORG_ID ?? config?.preferences?.orgId;
        if (!resolvedTaskOrgId) {
            tui.fatal(`Organization ID required to resolve task '${identifier}'. Use --org-id or set AGENTUITY_CLOUD_ORG_ID.`, ErrorCode.INVALID_ARGUMENT);
        }
        const taskAdapter = createServerFetchAdapter({
            headers: {
                Authorization: `Bearer ${auth.apiKey}`,
                'x-agentuity-orgid': resolvedTaskOrgId,
            },
        }, logger);
        const taskService = new TaskStorageService(taskBaseUrl, taskAdapter);
        const taskResult = await taskService.get(identifier);
        if (taskResult) {
            region = taskDefaultRegion;
            orgId = resolvedTaskOrgId;
        }
    }
    else if (identifierType === 'sandbox') {
        // sandbox - use CLI API to resolve across all orgs the user has access to
        if (!apiClient) {
            tui.fatal(`API client required for sandbox region lookup. This is an internal error.`, ErrorCode.INVALID_ARGUMENT);
        }
        const sandbox = await sandboxResolve(apiClient, identifier);
        region = sandbox.region ?? null;
        // Cache the orgId along with the region for future lookups
        if (sandbox.orgId) {
            orgId = sandbox.orgId;
        }
    }
    else if (identifierType === 'webhook') {
        // Webhook tenant DB is not regional — any global Catalyst can serve the request.
        // We still look up the webhook to validate it exists and cache the orgId.
        if (!apiClient) {
            tui.fatal(`API client required for webhook region lookup. This is an internal error.`, ErrorCode.INVALID_ARGUMENT);
        }
        const resolvedOrgId = orgId ?? process.env.AGENTUITY_CLOUD_ORG_ID ?? config?.preferences?.orgId;
        const webhook = await getWebhook(apiClient, identifier, resolvedOrgId ? { orgId: resolvedOrgId } : undefined);
        if (webhook) {
            orgId = resolvedOrgId;
        }
        // Use default region since webhooks are global
        region = await getDefaultRegion(profileName, config);
    }
    else {
        // stream - use the streams service to look up stream info
        // Any regional streams service can look up any stream and return its info
        // The service authenticates based on user's org membership, no explicit orgId needed
        const defaultRegion = await getDefaultRegion(profileName, config);
        const baseUrl = getServiceUrls(defaultRegion).stream;
        // Include orgId if available, but don't require it
        const resolvedOrgId = orgId ?? process.env.AGENTUITY_CLOUD_ORG_ID ?? config?.preferences?.orgId;
        const adapter = createServerFetchAdapter({
            headers: {
                Authorization: `Bearer ${auth.apiKey}`,
            },
            queryParams: resolvedOrgId ? { orgId: resolvedOrgId } : undefined,
        }, logger);
        const streamService = new StreamStorageService(baseUrl, adapter);
        const streamInfo = await streamService.get(identifier);
        // Extract region from the stream URL (e.g., https://streams-use.agentuity.cloud/...)
        const urlMatch = streamInfo.url.match(/https:\/\/streams-([^.]+)\.agentuity\.cloud/);
        if (urlMatch?.[1]) {
            region = urlMatch[1];
        }
        else if (streamInfo.url.includes('streams.agentuity.io')) {
            // Local environment
            region = 'local';
        }
    }
    if (!region) {
        tui.fatal(`Could not determine region for ${identifierType} '${identifier}'. Use --region flag to specify.`, ErrorCode.RESOURCE_NOT_FOUND);
    }
    // Validate region is a non-empty string
    if (typeof region !== 'string' || region.trim() === '') {
        tui.fatal(`Invalid region returned for ${identifierType} '${identifier}': '${region}'. Use --region flag to specify a valid region.`, ErrorCode.RESOURCE_NOT_FOUND);
    }
    // Cache the result
    await setResourceInfo(identifierType, profileName, identifier, region, orgId);
    logger.trace(`[region-lookup] Cached region for ${identifier}: ${region}`);
    return region;
}
/**
 * Cache the region for a project after creation
 */
export async function cacheProjectRegion(profileName = 'production', projectId, region) {
    await setResourceInfo('project', profileName, projectId, region);
}
//# sourceMappingURL=region-lookup.js.map