/*
 * Copyright OpenSearch Contributors
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * OpenSearch Storage Client
 *
 * Frontend client for OpenSearch storage operations.
 * All requests go through the backend API at /api/storage/*
 */
import { ENV_CONFIG } from '../../lib/config.js';
const STORAGE_BASE_URL = ENV_CONFIG.storageApiUrl;
/**
 * Generic HTTP client for storage API
 * Backend handles config resolution (file or env vars) - no headers needed from frontend
 */
async function request(method, endpoint, body) {
    const url = `${STORAGE_BASE_URL}${endpoint}`;
    const options = {
        method,
        headers: {
            'Content-Type': 'application/json',
        },
    };
    if (body) {
        options.body = JSON.stringify(body);
    }
    const response = await fetch(url, options);
    if (!response.ok) {
        const errorData = await response.json().catch(() => ({ error: response.statusText }));
        throw new Error(errorData.error || `Storage request failed: ${response.status}`);
    }
    return response.json();
}
// ==================== Admin API ====================
export const storageAdmin = {
    /**
     * Check storage health/connectivity
     */
    async health() {
        return request('GET', '/health');
    },
    /**
     * Initialize all indexes with mappings
     */
    async initIndexes() {
        return request('POST', '/init-indexes');
    },
    /**
     * Get storage statistics
     */
    async stats() {
        return request('GET', '/stats');
    },
};
// ==================== Test Cases API ====================
export const testCaseStorage = {
    /**
     * Get all test cases (latest versions only)
     * @param options.fields - 'summary' for lightweight list-view payload
     * @param options.size - page size for pagination
     * @param options.after - cursor token for next page
     * @param options.includeSample - whether to include sample/demo data
     */
    async getAll(options) {
        const params = new URLSearchParams();
        if (options?.fields)
            params.append('fields', options.fields);
        if (options?.size)
            params.append('size', options.size.toString());
        if (options?.after)
            params.append('after', options.after);
        if (options?.includeSample !== undefined)
            params.append('includeSample', String(options.includeSample));
        const query = params.toString() ? `?${params.toString()}` : '';
        return request('GET', `/test-cases${query}`);
    },
    /**
     * Get test cases by specific IDs (latest versions only)
     * Used for efficient filtered fetching (e.g., only test cases in a benchmark)
     */
    async getByIds(ids) {
        if (ids.length === 0)
            return [];
        const idsParam = ids.join(',');
        const result = await request('GET', `/test-cases?ids=${idsParam}`);
        return result.testCases;
    },
    /**
     * Get test case by ID (latest version)
     */
    async getById(id) {
        try {
            return await request('GET', `/test-cases/${id}`);
        }
        catch (error) {
            const msg = error.message.toLowerCase();
            if (msg.includes('404') || msg.includes('not found')) {
                return null;
            }
            throw error;
        }
    },
    /**
     * Get all versions of a test case
     */
    async getVersions(id) {
        const result = await request('GET', `/test-cases/${id}/versions`);
        return result.versions;
    },
    /**
     * Get specific version of a test case
     */
    async getVersion(id, version) {
        try {
            return await request('GET', `/test-cases/${id}/versions/${version}`);
        }
        catch (error) {
            const msg = error.message.toLowerCase();
            if (msg.includes('404') || msg.includes('not found')) {
                return null;
            }
            throw error;
        }
    },
    /**
     * Create new test case (starts at version 1)
     */
    async create(testCase) {
        return request('POST', '/test-cases', testCase);
    },
    /**
     * Update test case (creates new version)
     */
    async update(id, testCase) {
        return request('PUT', `/test-cases/${id}`, testCase);
    },
    /**
     * Delete test case (all versions)
     */
    async delete(id) {
        return request('DELETE', `/test-cases/${id}`);
    },
    /**
     * Bulk create test cases
     */
    async bulkCreate(testCases) {
        return request('POST', '/test-cases/bulk', { testCases });
    },
};
// ==================== Benchmarks API ====================
export const benchmarkStorage = {
    /**
     * Get all benchmarks
     * @param options.includeSample - whether to include sample/demo data
     */
    async getAll(options) {
        const params = new URLSearchParams();
        if (options?.includeSample !== undefined)
            params.append('includeSample', String(options.includeSample));
        const query = params.toString() ? `?${params.toString()}` : '';
        const result = await request('GET', `/benchmarks${query}`);
        return result.benchmarks;
    },
    /**
     * Get benchmark by ID
     * @param options.fields - 'polling' for lightweight payload (excludes versions, testCaseSnapshots, headers)
     * @param options.runsSize - max number of runs to return
     * @param options.runsOffset - offset into runs array for pagination
     */
    async getById(id, options) {
        try {
            const params = new URLSearchParams();
            if (options?.fields)
                params.append('fields', options.fields);
            if (options?.runsSize !== undefined)
                params.append('runsSize', options.runsSize.toString());
            if (options?.runsOffset !== undefined)
                params.append('runsOffset', options.runsOffset.toString());
            const query = params.toString() ? `?${params.toString()}` : '';
            return await request('GET', `/benchmarks/${id}${query}`);
        }
        catch (error) {
            const msg = error.message.toLowerCase();
            if (msg.includes('404') || msg.includes('not found')) {
                return null;
            }
            throw error;
        }
    },
    /**
     * Create benchmark
     */
    async create(benchmark) {
        return request('POST', '/benchmarks', benchmark);
    },
    /**
     * Update benchmark (for run management)
     */
    async update(id, benchmark) {
        return request('PUT', `/benchmarks/${id}`, benchmark);
    },
    /**
     * Delete benchmark
     */
    async delete(id) {
        return request('DELETE', `/benchmarks/${id}`);
    },
    /**
     * Bulk create benchmarks
     */
    async bulkCreate(benchmarks) {
        return request('POST', '/benchmarks/bulk', { benchmarks });
    },
    /**
     * Update benchmark metadata only (name, description)
     */
    async updateMetadata(id, updates) {
        return request('PATCH', `/benchmarks/${id}/metadata`, updates);
    },
    /**
     * Get all versions of a benchmark
     */
    async getVersions(id) {
        return request('GET', `/benchmarks/${id}/versions`);
    },
    /**
     * Get specific version of a benchmark
     */
    async getVersion(id, version) {
        return request('GET', `/benchmarks/${id}/versions/${version}`);
    },
};
// Backwards compatibility alias
/** @deprecated Use benchmarkStorage instead */
export const experimentStorage = benchmarkStorage;
// ==================== Runs API ====================
export const runStorage = {
    /**
     * Get all runs with pagination
     */
    async getAll(options = {}) {
        const params = new URLSearchParams();
        if (options.size)
            params.append('size', options.size.toString());
        if (options.from)
            params.append('from', options.from.toString());
        if (options._source && options._source.length > 0) {
            params.append('fields', options._source.join(','));
        }
        const query = params.toString() ? `?${params.toString()}` : '';
        return request('GET', `/runs${query}`);
    },
    /**
     * Get run by ID
     */
    async getById(id) {
        try {
            return await request('GET', `/runs/${id}`);
        }
        catch (error) {
            const msg = error.message.toLowerCase();
            if (msg.includes('404') || msg.includes('not found')) {
                return null;
            }
            throw error;
        }
    },
    /**
     * Create run
     */
    async create(run, options) {
        const query = options?.analytics === false ? '?analytics=false' : '';
        return request('POST', `/runs${query}`, run);
    },
    /**
     * Delete run
     */
    async delete(id) {
        return request('DELETE', `/runs/${id}`);
    },
    /**
     * Partial update of a run
     * Used for updating trace-mode runs after traces become available
     */
    async partialUpdate(id, updates) {
        return request('PATCH', `/runs/${id}`, updates);
    },
    /**
     * Get run counts grouped by test case ID (single aggregation query)
     */
    async getCountsByTestCase() {
        const result = await request('GET', '/runs/counts-by-test-case');
        return result.counts;
    },
    /**
     * Get runs by test case ID
     */
    async getByTestCase(testCaseId, size, from) {
        const params = new URLSearchParams();
        if (size !== undefined)
            params.set('size', String(size));
        if (from !== undefined)
            params.set('from', String(from));
        const query = params.toString() ? `?${params}` : '';
        return request('GET', `/runs/by-test-case/${testCaseId}${query}`);
    },
    /**
     * Get runs by benchmark ID
     */
    async getByBenchmark(benchmarkId, size) {
        const query = size ? `?size=${size}` : '';
        const result = await request('GET', `/runs/by-benchmark/${benchmarkId}${query}`);
        return result.runs;
    },
    /**
     * Get runs by benchmark run config ID
     */
    async getByBenchmarkRun(benchmarkId, runId, size) {
        const query = size ? `?size=${size}` : '';
        const result = await request('GET', `/runs/by-benchmark-run/${benchmarkId}/${runId}${query}`);
        return result.runs;
    },
    /**
     * Get all iterations for a test case in a benchmark
     */
    async getIterations(benchmarkId, testCaseId, benchmarkRunId) {
        const params = new URLSearchParams();
        if (benchmarkRunId)
            params.append('benchmarkRunId', benchmarkRunId);
        const query = params.toString() ? `?${params.toString()}` : '';
        return request('GET', `/runs/iterations/${benchmarkId}/${testCaseId}${query}`);
    },
    // Backwards compatibility aliases
    /** @deprecated Use getByBenchmark instead */
    async getByExperiment(experimentId, size) {
        return this.getByBenchmark(experimentId, size);
    },
    /** @deprecated Use getByBenchmarkRun instead */
    async getByExperimentRun(experimentId, runId, size) {
        return this.getByBenchmarkRun(experimentId, runId, size);
    },
    /**
     * Search runs with filters
     */
    async search(filters) {
        return request('POST', '/runs/search', filters);
    },
    /**
     * Add annotation to run
     */
    async addAnnotation(runId, annotation) {
        return request('POST', `/runs/${runId}/annotations`, annotation);
    },
    /**
     * Update annotation
     */
    async updateAnnotation(runId, annotationId, updates) {
        return request('PUT', `/runs/${runId}/annotations/${annotationId}`, updates);
    },
    /**
     * Delete annotation
     */
    async deleteAnnotation(runId, annotationId) {
        return request('DELETE', `/runs/${runId}/annotations/${annotationId}`);
    },
    /**
     * Bulk create runs
     */
    async bulkCreate(runs) {
        return request('POST', '/runs/bulk', { runs });
    },
};
// ==================== Analytics API ====================
export const analyticsStorage = {
    /**
     * Query analytics records
     */
    async query(filters) {
        const params = new URLSearchParams();
        Object.entries(filters).forEach(([key, value]) => {
            if (value !== undefined)
                params.append(key, value.toString());
        });
        const query = params.toString() ? `?${params.toString()}` : '';
        return request('GET', `/analytics${query}`);
    },
    /**
     * Get aggregated metrics
     */
    async aggregations(experimentId, groupBy) {
        const params = new URLSearchParams();
        if (experimentId)
            params.append('experimentId', experimentId);
        if (groupBy)
            params.append('groupBy', groupBy);
        const query = params.toString() ? `?${params.toString()}` : '';
        return request('GET', `/analytics/aggregations${query}`);
    },
    /**
     * Complex search with custom filters and aggregations
     */
    async search(options) {
        return request('POST', '/analytics/search', options);
    },
    /**
     * Backfill analytics from existing runs
     */
    async backfill() {
        return request('POST', '/backfill-analytics');
    },
};
// ==================== Combined Export ====================
export const opensearchStorage = {
    admin: storageAdmin,
    testCases: testCaseStorage,
    benchmarks: benchmarkStorage,
    runs: runStorage,
    analytics: analyticsStorage,
    // Backwards compatibility alias
    /** @deprecated Use benchmarks instead */
    experiments: benchmarkStorage,
};
export default opensearchStorage;
//# sourceMappingURL=opensearchClient.js.map