/*
 * Runtime Web – Unified Serverless Framework for Full-Stack TypeScript Applications
 * Documentation: https://runtimeweb.com/docs/getting-started
 *
 * @template: ai-chat
 */

/**
 * Chat API Service
 *
 * Provides HTTP client methods for communicating with the AI Chat backend.
 * Supports both non-streaming and streaming (SSE) response modes.
 *
 * @module services/chat-api
 */

import type { ChatRequest, ChatResponse, StreamChunk } from '../types';

/** Base URL for API requests, configured via RUNTIME_ENV_API_BASE_URL environment variable */
const API_BASE_URL = typeof process !== 'undefined'
  ? process.env.RUNTIME_ENV_API_BASE_URL || ''
  : '';

/**
 * ChatApiService handles all HTTP communication with the AI Chat backend.
 */
export class ChatApiService {
    /**
     * Sends a chat message and returns the complete response.
     *
     * @param request - The chat request containing sessionId, message, and optional behavior
     * @returns Promise resolving to the chat response with AI-generated content
     * @throws Error if the request fails or returns a non-OK status
     */
    async sendMessage(request: ChatRequest): Promise<ChatResponse> {
        const response = await fetch(`${API_BASE_URL}/chat`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(request),
        });

        if (!response.ok) {
            const error = await response.json().catch(() => ({ error: 'Unknown error' }));
            throw new Error(error.error || `Request failed: ${response.status}`);
        }

        return response.json();
    }

    /**
     * Sends a chat message with streaming response.
     * Returns an async generator that yields chunks as they arrive via SSE.
     *
     * @param request - The chat request containing sessionId, message, and optional behavior
     * @yields StreamChunk objects containing token fragments
     * @throws Error if the request fails or has no response body
     */
    async *sendMessageStream(request: ChatRequest): AsyncGenerator<StreamChunk> {
        const response = await fetch(`${API_BASE_URL}/chat/stream`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'text/event-stream',
            },
            body: JSON.stringify(request),
        });

        if (!response.ok) {
            const error = await response.json().catch(() => ({ error: 'Unknown error' }));
            throw new Error(error.error || `Request failed: ${response.status}`);
        }

        const reader = response.body?.getReader();
        if (!reader) {
            throw new Error('No response body');
        }

        const decoder = new TextDecoder();
        let buffer = '';

        try {
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;

                buffer += decoder.decode(value, { stream: true });
                const lines = buffer.split('\n');
                buffer = lines.pop() || '';

                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        const data = line.slice(6);
                        if (data === '[DONE]') {
                            return;
                        }
                        try {
                            yield JSON.parse(data) as StreamChunk;
                        } catch {
                            // Skip invalid JSON chunks
                        }
                    }
                }
            }
        } finally {
            reader.releaseLock();
        }
    }

    /**
     * Performs a health check against the backend.
     *
     * @returns Promise resolving to true if healthy, false if unhealthy or unreachable
     */
    async healthCheck(): Promise<boolean> {
        try {
            const response = await fetch(`${API_BASE_URL}/health`);
            return response.ok;
        } catch {
            return false;
        }
    }
}

/** Singleton instance of ChatApiService */
export const chatApiService = new ChatApiService();
