// API client for Otelite dashboard

const API_BASE = '/api';

/**
 * API client class
 */
class ApiClient {
    constructor() {
        this.baseUrl = API_BASE;
    }

    /**
     * Make a GET request
     */
    async get(endpoint, params = {}) {
        const url = new URL(`${this.baseUrl}${endpoint}`, window.location.origin);

        // Add query parameters
        Object.keys(params).forEach(key => {
            if (params[key] !== null && params[key] !== undefined) {
                url.searchParams.append(key, params[key]);
            }
        });

        try {
            const response = await fetch(url);

            if (!response.ok) {
                let detail = response.statusText;
                try {
                    const body = await response.json();
                    detail = body.error || body.message || response.statusText;
                } catch { /* body not JSON, keep statusText */ }
                throw new Error(`HTTP ${response.status}: ${detail}`);
            }

            return await response.json();
        } catch (error) {
            console.error('API GET failed:', endpoint, error);
            throw error;
        }
    }

    /**
     * Fetch logs with optional filters
     */
    async getLogs(filters = {}) {
        return this.get('/logs', filters);
    }

    /**
     * Fetch a single log by ID
     */
    async getLog(id) {
        return this.get(`/logs/${id}`);
    }

    /**
     * Export logs — returns a Blob for the caller to download
     */
    async exportLogs(params = {}) {
        const url = new URL(`${this.baseUrl}/logs/export`, window.location.origin);
        Object.keys(params).forEach(key => {
            if (params[key] !== null && params[key] !== undefined) {
                url.searchParams.append(key, params[key]);
            }
        });
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        return response.blob();
    }

    /**
     * Fetch traces with optional filters
     */
    async getTraces(filters = {}) {
        return this.get('/traces', filters);
    }

    /**
     * Fetch a single trace by ID
     */
    async getTrace(traceId) {
        return this.get(`/traces/${traceId}`);
    }

    /**
     * Export traces — returns a Blob for the caller to download
     */
    async exportTraces(params = {}) {
        const url = new URL(`${this.baseUrl}/traces/export`, window.location.origin);
        Object.keys(params).forEach(key => {
            if (params[key] !== null && params[key] !== undefined) {
                url.searchParams.append(key, params[key]);
            }
        });
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        return response.blob();
    }

    /**
     * Fetch metrics with optional filters
     */
    async getMetrics(filters = {}) {
        return this.get('/metrics', filters);
    }

    /**
     * Fetch list of metric names
     */
    async getMetricNames() {
        return this.get('/metrics/names');
    }

    /**
     * Fetch aggregated metrics
     */
    async getAggregatedMetrics(params = {}) {
        return this.get('/metrics/aggregate', params);
    }

    /**
     * Fetch time-series data for a specific metric
     */
    async getMetricTimeseries(name, params = {}) {
        return this.get(`/metrics/${encodeURIComponent(name)}/timeseries`, params);
    }

    /**
     * Export metrics — returns a Blob for the caller to download
     */
    async exportMetrics(params = {}) {
        const url = new URL(`${this.baseUrl}/metrics/export`, window.location.origin);
        Object.keys(params).forEach(key => {
            if (params[key] !== null && params[key] !== undefined) {
                url.searchParams.append(key, params[key]);
            }
        });
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
        return response.blob();
    }

    /**
     * Fetch distinct resource attribute keys for a signal type.
     * signal: "logs", "spans", or "metrics"
     */
    async getResourceKeys(signal) {
        return this.get('/resource-keys', { signal });
    }

    /**
     * Fetch GenAI token usage statistics
     */
    async getTokenUsage(params = {}) {
        return this.get('/genai/usage', params);
    }

    /**
     * Fetch GenAI cost time-series buckets
     */
    async getCostSeries(params = {}) {
        return this.get('/genai/cost_series', params);
    }

    /**
     * Fetch top-N most expensive GenAI spans
     */
    async getTopSpans(params = {}) {
        return this.get('/genai/top_spans', params);
    }

    /**
     * Fetch GenAI finish-reason distribution
     */
    async getFinishReasons(params = {}) {
        return this.get('/genai/finish_reasons', params);
    }

    async getLatencyStats(params = {}) { return this.get('/genai/latency_stats', params); }
    async getErrorRate(params = {}) { return this.get('/genai/error_rate', params); }
    async getToolUsage(params = {}) { return this.get('/genai/tool_usage', params); }
    async getRetryStats(params = {}) { return this.get('/genai/retry_stats', params); }
    async getRetrievalStats(params = {}) { return this.get('/genai/retrieval_stats', params); }
    async getPricingMetadata() { return this.get('/genai/pricing_metadata'); }
    async getAgentFrameworkDefs() { return this.get('/genai/agent_framework_defs'); }
    async getTopSessions(params = {}) { return this.get('/genai/top_sessions', params); }
    async getTopConversations(params = {}) { return this.get('/genai/top_conversations', params); }
    async getTruncationRate(params = {}) { return this.get('/genai/truncation_rate', params); }
    async getCacheHitRate(params = {}) { return this.get('/genai/cache_hit_rate', params); }
    async getRequestParamProfile(params = {}) { return this.get('/genai/request_param_profile', params); }
    async getConversationDepth(params = {}) { return this.get('/genai/conversation_depth', params); }
    async getCallsSeries(params = {}) { return this.get('/genai/calls_series', { bucket_secs: 3600, ...params }); }
    async getErrorTypes(params = {})  { return this.get('/genai/error_types', params); }
    async getModelDrift(params = {})  { return this.get('/genai/model_drift', params); }

    /**
     * Check health status
     */
    async getHealth() {
        return this.get('/health');
    }

    /**
     * Fetch storage statistics
     */
    async getStats() {
        return this.get('/stats');
    }
}

// Export singleton instance
export const api = new ApiClient();
