package adk

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/orchard9/stemedb-go/steme"
)

// AssertTool stores knowledge with lifecycle and confidence.
//
// Used by Research Agent and Human Supervisor to store assertions.
type AssertTool struct {
	client EpistemeClient
}

// NewAssertTool creates a new Assert tool.
func NewAssertTool(client EpistemeClient) *AssertTool {
	return &AssertTool{client: client}
}

// Name returns the tool name.
func (t *AssertTool) Name() string {
	return "episteme_assert"
}

// Description returns the tool description.
func (t *AssertTool) Description() string {
	return "Store knowledge assertion in Episteme. " +
		"Always include source_hash for provenance. " +
		"Use confidence to express uncertainty. " +
		"Mark as lifecycle=proposed unless explicitly approved."
}

// Execute performs the assert operation.
func (t *AssertTool) Execute(ctx context.Context, input []byte) ([]byte, error) {
	var params AssertInput
	if err := json.Unmarshal(input, &params); err != nil {
		return nil, fmt.Errorf("invalid assert input: %w", err)
	}

	// Build assertion
	builder := steme.NewAssertion(params.Subject, params.Predicate)

	// Set object value based on type
	if err := setObjectValue(builder, params.Object); err != nil {
		errorOutput, marshalErr := json.Marshal(AssertOutput{
			Success: false,
			Error:   err.Error(),
		})
		if marshalErr != nil {
			return nil, fmt.Errorf("invalid object value: %w", err)
		}
		return errorOutput, nil
	}

	builder.WithConfidence(float64(params.Confidence)).
		WithSourceHash(params.SourceHash)

	if params.Lifecycle != "" {
		lifecycle := parseLifecycle(params.Lifecycle)
		builder.WithLifecycle(lifecycle)
	}

	if params.ParentHash != "" {
		builder.WithParentHash(params.ParentHash)
	}

	// Execute assertion
	hash, err := t.client.Assert(ctx, builder.Build())
	if err != nil {
		errorOutput, marshalErr := json.Marshal(AssertOutput{
			Success: false,
			Error:   err.Error(),
		})
		if marshalErr != nil {
			return nil, fmt.Errorf("assertion failed: %w", err)
		}
		return errorOutput, nil
	}

	outputBytes, err := json.Marshal(AssertOutput{
		Hash:    hash,
		Success: true,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to marshal assert output: %w", err)
	}
	return outputBytes, nil
}
