package anthropic

import (
	"bufio"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
)

// Anthropic SSE event types handled by PipeAnthropicSSE.
const (
	eventContentBlockDelta = "content_block_delta"
	eventMessageStop       = "message_stop"
)

// anthropicStreamEvent is the data payload for a content_block_delta SSE event.
type anthropicStreamEvent struct {
	Type  string         `json:"type"`
	Delta anthropicDelta `json:"delta"`
}

type anthropicDelta struct {
	Type string `json:"type"`
	Text string `json:"text"`
}

// openAIChunk is the minimal OpenAI-compatible SSE chunk emitted to the client.
type openAIChunk struct {
	ID      string              `json:"id"`
	Object  string              `json:"object"`
	Choices []openAIChunkChoice `json:"choices"`
}

type openAIChunkChoice struct {
	Index int             `json:"index"`
	Delta openAIChunkDelta `json:"delta"`
}

type openAIChunkDelta struct {
	Content string `json:"content"`
}

// PipeAnthropicSSE reads Anthropic's event-typed SSE stream and re-emits each
// text chunk as an OpenAI-compatible SSE event. It terminates on message_stop
// or when the upstream body is exhausted.
//
// Anthropic SSE format:
//
//	event: content_block_delta
//	data: {"type":"content_block_delta","delta":{"type":"text_delta","text":"Hello"}}
//
// Re-emitted as OpenAI-compat:
//
//	data: {"id":"chatcmpl-anthropic","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hello"}}]}
func PipeAnthropicSSE(body *bufio.Scanner, w http.ResponseWriter) error {
	flusher, ok := w.(http.Flusher)
	if !ok {
		return fmt.Errorf("response writer does not support flushing (SSE not possible)")
	}

	var currentEvent string

	for body.Scan() {
		line := body.Text()

		// Track the event type from "event: ..." lines.
		if strings.HasPrefix(line, "event: ") {
			currentEvent = strings.TrimPrefix(line, "event: ")
			continue
		}

		// Skip blank lines and lines without a data prefix.
		if line == "" || !strings.HasPrefix(line, "data: ") {
			continue
		}

		rawData := strings.TrimPrefix(line, "data: ")

		switch currentEvent {
		case eventContentBlockDelta:
			var evt anthropicStreamEvent
			if err := json.Unmarshal([]byte(rawData), &evt); err != nil {
				continue // skip malformed events gracefully
			}
			if evt.Delta.Type != "text_delta" || evt.Delta.Text == "" {
				continue
			}
			chunk := openAIChunk{
				ID:     "chatcmpl-anthropic",
				Object: "chat.completion.chunk",
				Choices: []openAIChunkChoice{{
					Index: 0,
					Delta: openAIChunkDelta{Content: evt.Delta.Text},
				}},
			}
			chunkJSON, err := json.Marshal(chunk)
			if err != nil {
				continue
			}
			if _, err := fmt.Fprintf(w, "data: %s\n\n", chunkJSON); err != nil {
				return fmt.Errorf("writing SSE chunk: %w", err)
			}
			flusher.Flush()

		case eventMessageStop:
			if _, err := fmt.Fprintf(w, "data: [DONE]\n\n"); err != nil {
				return fmt.Errorf("writing SSE done: %w", err)
			}
			flusher.Flush()
			return nil
		}
	}

	if err := body.Err(); err != nil {
		return fmt.Errorf("reading Anthropic SSE body: %w", err)
	}
	return nil
}
