package knowledgeqa

import (
	"context"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/knowledgeqa/protocol"
)

// FeedbackSnapshot is the bounded, owner-authorized copy of one completed
// answer that may leave the workspace data path for AgentTeam product improvement.
// It deliberately excludes source bodies, debug model output, error detail,
// usage, settlement references, and credentials.
type FeedbackSnapshot struct {
	Turn            Turn
	ThreadChannelID string
	Answer          string
	Activities      []protocol.RuntimeActivity
	Citations       []Citation
}

func (store *Store) LoadFeedbackSnapshotForOwner(
	ctx context.Context,
	workspaceID string,
	ownerUserID string,
	sessionID string,
	turnID string,
) (FeedbackSnapshot, error) {
	if store == nil || store.db == nil {
		return FeedbackSnapshot{}, fmt.Errorf("knowledge Q&A store is not configured")
	}
	workspaceID = strings.TrimSpace(workspaceID)
	ownerUserID = strings.TrimSpace(ownerUserID)
	sessionID = strings.TrimSpace(sessionID)
	turnID = strings.TrimSpace(turnID)
	if workspaceID == "" || ownerUserID == "" || sessionID == "" || turnID == "" {
		return FeedbackSnapshot{}, ErrNotFound
	}

	session, err := store.LoadSessionForOwner(ctx, workspaceID, ownerUserID, sessionID)
	if err != nil {
		return FeedbackSnapshot{}, err
	}
	turn, err := loadTurn(ctx, store.db, workspaceID, turnID)
	if err != nil {
		return FeedbackSnapshot{}, err
	}
	if turn.SessionID != session.ID {
		return FeedbackSnapshot{}, ErrNotFound
	}
	if turn.Status != "completed" || strings.TrimSpace(turn.AssistantMessageID) == "" {
		return FeedbackSnapshot{}, ErrInvalidState
	}

	var answer string
	if err := store.db.QueryRow(ctx, `
SELECT content
FROM scope_messages
WHERE workspace_id=$1 AND scope_id=$2 AND id=$3
`, workspaceID, session.ThreadChannelID, turn.AssistantMessageID).Scan(&answer); err != nil {
		return FeedbackSnapshot{}, fmt.Errorf("load Knowledge Q&A feedback answer: %w", err)
	}
	answer = strings.TrimSpace(answer)
	if answer == "" {
		return FeedbackSnapshot{}, ErrInvalidState
	}

	activities, err := store.listFeedbackActivities(ctx, turn)
	if err != nil {
		return FeedbackSnapshot{}, err
	}
	citations, err := store.listFeedbackCitations(ctx, turn)
	if err != nil {
		return FeedbackSnapshot{}, err
	}
	turn.Activities = nil
	turn.DebugModelOutput = ""
	turn.ErrorDetail = ""
	return FeedbackSnapshot{
		Turn:            turn,
		ThreadChannelID: session.ThreadChannelID,
		Answer:          answer,
		Activities:      activities,
		Citations:       citations,
	}, nil
}

func (store *Store) listFeedbackActivities(
	ctx context.Context,
	turn Turn,
) ([]protocol.RuntimeActivity, error) {
	rows, err := store.db.Query(ctx, `
SELECT event.sequence, event.kind, event.status, event.summary,
       event.tool_name, event.payload_json, event.created_at
FROM knowledge_qa_events AS event
WHERE event.workspace_id=$1 AND event.turn_id=$2 AND event.attempt_id=$3
ORDER BY event.sequence ASC
`, turn.WorkspaceID, turn.ID, turn.CurrentAttemptID)
	if err != nil {
		return nil, fmt.Errorf("list Knowledge Q&A feedback activities: %w", err)
	}
	defer rows.Close()
	activities := make([]protocol.RuntimeActivity, 0)
	for rows.Next() {
		var activity protocol.RuntimeActivity
		var payload []byte
		if err := rows.Scan(
			&activity.Sequence, &activity.Kind, &activity.Status,
			&activity.Summary, &activity.ToolName, &payload, &activity.CreatedAt,
		); err != nil {
			return nil, fmt.Errorf("scan Knowledge Q&A feedback activity: %w", err)
		}
		projectRuntimeActivityPayload(&activity, payload)
		activity.ID = fmt.Sprintf("%s:%d", turn.ID, activity.Sequence)
		activity.UpdatedAt = activity.CreatedAt
		activities = append(activities, activity)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate Knowledge Q&A feedback activities: %w", err)
	}
	return activities, nil
}

func (store *Store) listFeedbackCitations(ctx context.Context, turn Turn) ([]Citation, error) {
	rows, err := store.db.Query(ctx, `
SELECT id, workspace_id, turn_id, attempt_id, knowledge_base_id,
       COALESCE(source_id,''), root_kind, repo_role, revision,
       resolved_ref, resolved_ref_kind, path, line_start, line_end, created_at
FROM knowledge_qa_citations
WHERE workspace_id=$1 AND turn_id=$2 AND attempt_id=$3
ORDER BY id ASC
`, turn.WorkspaceID, turn.ID, turn.CurrentAttemptID)
	if err != nil {
		return nil, fmt.Errorf("list Knowledge Q&A feedback citations: %w", err)
	}
	defer rows.Close()
	citations := make([]Citation, 0)
	for rows.Next() {
		var citation Citation
		if err := rows.Scan(
			&citation.ID, &citation.WorkspaceID, &citation.TurnID,
			&citation.AttemptID, &citation.KnowledgeBaseID, &citation.SourceID,
			&citation.RootKind, &citation.RepoRole, &citation.Revision,
			&citation.ResolvedRef, &citation.ResolvedRefKind, &citation.Path,
			&citation.LineStart, &citation.LineEnd, &citation.CreatedAt,
		); err != nil {
			return nil, fmt.Errorf("scan Knowledge Q&A feedback citation: %w", err)
		}
		citations = append(citations, citation)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate Knowledge Q&A feedback citations: %w", err)
	}
	return citations, nil
}
