package action

import (
	"context"
	"fmt"

	"github.com/rockliang/poimen/workflows/action/llm"
	"github.com/rockliang/poimen/workflows/statemachine"
)

// LLMInferenceInput is input for LLMInferenceActivity
type LLMInferenceInput struct {
	Model         string                 `json:"model"`          // Model ID (reasoning, ornith:35b, etc)
	SystemPrompt  string                 `json:"system_prompt"`  // System instruction
	UserPrompt    string                 `json:"user_prompt"`    // User message
	Temperature   float64                `json:"temperature,omitempty"`   // LLM temperature (0-1)
	MaxTokens     int                    `json:"max_tokens,omitempty"`    // Max output tokens
	AuthToken     string                 `json:"auth_token,omitempty"`    // JWT token for authenticated endpoints
}

// LLMInferenceOutput is output from LLMInferenceActivity
type LLMInferenceOutput struct {
	Response     string `json:"response"`      // LLM response text
	Model        string `json:"model"`         // Model used
	StopReason   string `json:"stop_reason"`   // How inference stopped (stop_sequence, length, etc)
	TokensUsed   int    `json:"tokens_used"`   // Total tokens consumed
	ErrorMessage string `json:"error,omitempty"`
}

// LLMInferenceActivity calls LLM API with given prompt and returns response
func LLMInferenceActivity(ctx context.Context, in LLMInferenceInput) (LLMInferenceOutput, error) {
	logger := newActivityLogger(ctx)

	output := LLMInferenceOutput{
		Model: in.Model,
	}

	// Validate input
	if in.Model == "" {
		return output, fmt.Errorf("model not specified")
	}

	if in.UserPrompt == "" {
		return output, fmt.Errorf("user_prompt not specified")
	}

	logger.logf("info", "Starting LLM inference with model: %s", in.Model)

	// Create LLM client
	client, err := llm.NewClient()
	if err != nil {
		output.ErrorMessage = err.Error()
		return output, fmt.Errorf("failed to create LLM client: %w", err)
	}

	// Call LLM
	logger.logf("info", "Calling LLM API (model=%s, prompt_len=%d, auth=%v)", in.Model, len(in.UserPrompt), in.AuthToken != "")

	response, err := client.CreateMessage(ctx, llm.MessageInput{
		Model: statemachine.ModelSpec{
			ModelID: in.Model,
		},
		SystemPrompt: in.SystemPrompt,
		Messages: []llm.MessageParam{
			{
				Role:    "user",
				Content: in.UserPrompt,
			},
		},
		AuthToken: in.AuthToken,
	})

	if err != nil {
		output.ErrorMessage = err.Error()
		logger.logf("error", "LLM API call failed: %v", err)
		return output, fmt.Errorf("LLM inference failed: %w", err)
	}

	output.Response = response
	output.StopReason = "stop_sequence"

	logger.logf("info", "LLM inference completed (response_len=%d)", len(response))

	return output, nil
}

// LLMBatchInferenceInput is input for batch inference
type LLMBatchInferenceInput struct {
	Model        string                   `json:"model"`
	SystemPrompt string                   `json:"system_prompt"`
	Prompts      []string                 `json:"prompts"`       // List of user prompts
	Temperature  float64                  `json:"temperature,omitempty"`
	AuthToken    string                   `json:"auth_token,omitempty"`    // JWT token for authenticated endpoints
}

// LLMBatchInferenceOutput is output from batch inference
type LLMBatchInferenceOutput struct {
	Responses []string `json:"responses"`     // LLM responses (parallel to input Prompts)
	Model     string   `json:"model"`
	Errors    []string `json:"errors,omitempty"`
}

// LLMBatchInferenceActivity calls LLM multiple times in sequence
func LLMBatchInferenceActivity(ctx context.Context, in LLMBatchInferenceInput) (LLMBatchInferenceOutput, error) {
	logger := newActivityLogger(ctx)

	output := LLMBatchInferenceOutput{
		Model:     in.Model,
		Responses: []string{},
		Errors:    []string{},
	}

	if in.Model == "" {
		return output, fmt.Errorf("model not specified")
	}

	if len(in.Prompts) == 0 {
		return output, fmt.Errorf("no prompts provided")
	}

	logger.logf("info", "Starting batch LLM inference (model=%s, count=%d)", in.Model, len(in.Prompts))

	// Create LLM client
	client, err := llm.NewClient()
	if err != nil {
		return output, fmt.Errorf("failed to create LLM client: %w", err)
	}

	// Process each prompt
	for i, prompt := range in.Prompts {
		logger.logf("info", "Processing prompt %d/%d", i+1, len(in.Prompts))

		response, err := client.CreateMessage(ctx, llm.MessageInput{
			Model: statemachine.ModelSpec{
				ModelID: in.Model,
			},
			SystemPrompt: in.SystemPrompt,
			Messages: []llm.MessageParam{
				{
					Role:    "user",
					Content: prompt,
				},
			},
		})

		if err != nil {
			output.Errors = append(output.Errors, fmt.Sprintf("prompt %d: %v", i, err))
			output.Responses = append(output.Responses, "")
			logger.logf("warn", "Failed to process prompt %d: %v", i, err)
		} else {
			output.Responses = append(output.Responses, response)
		}
	}

	logger.logf("info", "Batch inference completed (responses=%d, errors=%d)", 
		len(output.Responses), len(output.Errors))

	return output, nil
}
