package activity

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"time"
)

// QueryGraphRAGActivity queries Memory System for semantic relations
func QueryGraphRAGActivity(ctx context.Context, input GraphRAGQueryInput) (GraphRAGQueryOutput, error) {
	logger := newActivityLogger(ctx)
	output := GraphRAGQueryOutput{
		WorkflowID: input.WorkflowID,
		Query:      input.Query,
		Edges:      []EdgeWithWording{},
		Paths:      []QueryPathData{},
	}

	logger.Info("Querying GraphRAG: %s", input.Query)

	// Get Memory Service URL from env
	memoryURL := os.Getenv("MEMORY_SERVICE_URL")
	if memoryURL == "" {
		memoryURL = "http://localhost:8000"
	}

	// Build payload for Memory System
	payload := map[string]interface{}{
		"workflow_id":      input.WorkflowID,
		"query":            input.Query,
		"search_type":      input.SearchType,
		"relation_type":    input.RelationType,
		"confidence_floor": input.ConfidenceFloor,
		"top_k":            input.TopK,
		"ranking_profile":  input.RankingProfile,
		"canvas_nodes":     input.Canvas.Nodes,
		"canvas_edges":     input.Canvas.Edges,
		"relations":        input.Canvas.Relations,
	}

	reqBody, err := json.Marshal(payload)
	if err != nil {
		return output, fmt.Errorf("failed to marshal payload: %w", err)
	}

	// Call Memory System unified query endpoint
	req, err := http.NewRequestWithContext(
		ctx,
		"POST",
		memoryURL+"/workflows/query",
		bytes.NewReader(reqBody),
	)
	if err != nil {
		return output, fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	if token := ctx.Value("jwt_token"); token != nil {
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token))
	}

	startTime := time.Now()
	client := &http.Client{Timeout: 30 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return output, fmt.Errorf("failed to call Memory Service: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		body, _ := io.ReadAll(resp.Body)
		return output, fmt.Errorf("Memory Service returned %d: %s", resp.StatusCode, string(body))
	}

	// Parse response
	var graphResp struct {
		Edges      []EdgeWithWording `json:"edges"`
		Paths      []QueryPathData   `json:"paths"`
		TotalCount int               `json:"total_count"`
		HasMore    bool              `json:"has_more"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&graphResp); err != nil {
		return output, fmt.Errorf("failed to decode response: %w", err)
	}

	output.Edges = graphResp.Edges
	output.Paths = graphResp.Paths
	output.TotalCount = graphResp.TotalCount
	output.HasMore = graphResp.HasMore
	output.ExecutionMs = time.Since(startTime).Milliseconds()

	logger.Info("GraphRAG returned %d edges, %d paths in %dms", 
		len(output.Edges), len(output.Paths), output.ExecutionMs)
	return output, nil
}
