package memory

import (
	"context"
	"fmt"

	"go.temporal.io/sdk/activity"
)

// Activities memory service activities for Temporal workflows
type Activities struct {
	service *Service
}

// NewActivities creates memory service activities
func NewActivities(service *Service) *Activities {
	return &Activities{
		service: service,
	}
}

// CreateKnowledgeActivity creates knowledge record from workflow execution
func (a *Activities) CreateKnowledgeActivity(ctx context.Context, record *KnowledgeRecord) (string, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Creating knowledge", "title", record.Title)

	id, err := a.service.CreateKnowledge(ctx, record)
	if err != nil {
		logger.Error("Failed to create knowledge", "error", err)
		return "", err
	}

	logger.Info("Knowledge created", "id", id)
	return id, nil
}

// UpdateKnowledgeActivity updates existing knowledge record
func (a *Activities) UpdateKnowledgeActivity(ctx context.Context, record *KnowledgeRecord) (string, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Updating knowledge", "id", record.ID)

	id, err := a.service.UpdateKnowledge(ctx, record)
	if err != nil {
		logger.Error("Failed to update knowledge", "error", err)
		return "", err
	}

	logger.Info("Knowledge updated", "id", id)
	return id, nil
}

// SearchKnowledgeActivity searches knowledge base
func (a *Activities) SearchKnowledgeActivity(ctx context.Context, query string, opts *RetrievalOptions) ([]KnowledgeRecord, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Searching knowledge", "query", query)

	records, err := a.service.RetrieveKnowledge(ctx, query, opts)
	if err != nil {
		logger.Error("Search failed", "error", err)
		return nil, err
	}

	logger.Info("Found records", "count", len(records))
	return records, nil
}

// GetContextActivity retrieves context for tool/task (three-tier retrieval)
func (a *Activities) GetContextActivity(ctx context.Context, tool, task string, budget int) (*ServiceContext, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Getting context", "tool", tool, "task", task)

	svcCtx, err := a.service.RetrieveContext(ctx, tool, task, budget)
	if err != nil {
		logger.Error("Get context failed", "error", err)
		return nil, err
	}

	logger.Info("Retrieved context", "tier", svcCtx.Tier, "lessons", len(svcCtx.Lessons))
	return svcCtx, nil
}

// GetVaultActivity lists vault files
func (a *Activities) GetVaultActivity(ctx context.Context) ([]VaultInfo, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Fetching vault")

	files, err := a.service.GetVault(ctx)
	if err != nil {
		logger.Error("Get vault failed", "error", err)
		return nil, err
	}

	logger.Info("Vault files", "count", len(files))
	return files, nil
}

// HealthCheckActivity checks memory service health
func (a *Activities) HealthCheckActivity(ctx context.Context) (bool, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Checking memory service health")

	if !a.service.IsHealthy(ctx) {
		logger.Warn("Memory service is unhealthy")
		return false, fmt.Errorf("memory service unhealthy")
	}

	logger.Info("Memory service is healthy")
	return true, nil
}

// LearnFromExecutionActivity learns from task execution result
func (a *Activities) LearnFromExecutionActivity(ctx context.Context, taskID string, result string, tags []string) (string, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Learning from task execution", "taskID", taskID)

	metadata := map[string]interface{}{
		"task_id": taskID,
		"type":    "execution_result",
	}

	if len(tags) > 0 {
		metadata["tags"] = tags
	}

	id, err := a.service.CreateKnowledge(ctx, &KnowledgeRecord{
		Level:    "L1",
		Title:    fmt.Sprintf("Task Execution: %s", taskID),
		Content:  result,
		Source:   fmt.Sprintf("workflow://task/%s", taskID),
		Metadata: metadata,
	})

	if err != nil {
		logger.Error("Failed to learn from execution", "error", err)
		return "", err
	}

	logger.Info("Learned from execution", "id", id)
	return id, nil
}

// DiagnoseIssueActivity diagnoses issue using memory context
func (a *Activities) DiagnoseIssueActivity(ctx context.Context, tool, issue string) ([]string, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Diagnosing issue", "tool", tool, "issue", issue)

	svcCtx, err := a.service.RetrieveContext(ctx, tool, issue, 8192)
	if err != nil {
		logger.Error("Diagnosis failed", "error", err)
		return nil, err
	}

	// Extract recommendations
	recommendations := make([]string, 0)

	// Add tier-1 lessons (highest confidence)
	for _, lesson := range svcCtx.Lessons {
		if lesson.Tier == 1 {
			recommendations = append(recommendations, fmt.Sprintf("[Tier 1] %s", lesson.Text))
		}
	}

	// Add skills
	for _, skill := range svcCtx.Skills {
		recommendations = append(recommendations, fmt.Sprintf("[Skill] %s: %s", skill.Name, skill.Why))
	}

	// Add tier-2 lessons if no tier-1
	if len(recommendations) == 0 {
		for _, lesson := range svcCtx.Lessons {
			if lesson.Tier == 2 {
				recommendations = append(recommendations, fmt.Sprintf("[Tier 2] %s", lesson.Text))
			}
		}
	}

	logger.Info("Generated recommendations", "count", len(recommendations))
	return recommendations, nil
}

// AnalyzeErrorActivity analyzes error and retrieves relevant knowledge
func (a *Activities) AnalyzeErrorActivity(ctx context.Context, errorMsg string) ([]KnowledgeRecord, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Analyzing error")

	// Search for relevant knowledge
	records, err := a.service.RetrieveKnowledge(ctx, errorMsg, &RetrievalOptions{
		Limit:       10,
		LevelFilter: []string{"L1", "L2"},
		Floor:       0.6,
	})

	if err != nil {
		logger.Error("Error analysis failed", "error", err)
		return nil, err
	}

	logger.Info("Found relevant records for error", "count", len(records))
	return records, nil
}

// DocumentDecisionActivity documents workflow decision in knowledge base
func (a *Activities) DocumentDecisionActivity(ctx context.Context, decisionType string, decision string, reasoning string) (string, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Documenting decision", "type", decisionType)

	content := fmt.Sprintf("Decision: %s\n\nReasoning: %s", decision, reasoning)

	id, err := a.service.CreateKnowledge(ctx, &KnowledgeRecord{
		Level:   "L2",
		Title:   fmt.Sprintf("Decision: %s", decisionType),
		Content: content,
		Source:  fmt.Sprintf("workflow://decision/%s", decisionType),
		Metadata: map[string]interface{}{
			"decision_type": decisionType,
			"type":          "workflow_decision",
		},
	})

	if err != nil {
		logger.Error("Failed to document decision", "error", err)
		return "", err
	}

	logger.Info("Decision documented", "id", id)
	return id, nil
}

// SearchAndApplyActivity searches knowledge and applies it
func (a *Activities) SearchAndApplyActivity(ctx context.Context, query string, selector func(record *KnowledgeRecord) bool) ([]string, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Searching and applying", "query", query)

	records, err := a.service.RetrieveKnowledge(ctx, query, &RetrievalOptions{
		Limit: 10,
		Floor: 0.7,
	})

	if err != nil {
		logger.Error("Search and apply failed", "error", err)
		return nil, err
	}

	applied := make([]string, 0)
	for _, record := range records {
		if selector == nil || selector(&record) {
			applied = append(applied, record.Content)
			logger.Info("Applied knowledge", "id", record.ID)
		}
	}

	logger.Info("Applied knowledge records", "count", len(applied))
	return applied, nil
}

// RefreshMemoryActivity refreshes memory context (periodic activity)
func (a *Activities) RefreshMemoryActivity(ctx context.Context) (map[string]interface{}, error) {
	logger := activity.GetLogger(ctx)

	logger.Info("Refreshing memory context")

	vault, err := a.service.GetVault(ctx)
	if err != nil {
		logger.Error("Memory refresh failed", "error", err)
		return nil, err
	}

	healthy := a.service.IsHealthy(ctx)

	result := map[string]interface{}{
		"vault_files": len(vault),
		"healthy":     healthy,
	}

	logger.Info("Memory refreshed", "vault_files", len(vault), "healthy", healthy)
	return result, nil
}
