package message

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

// RecomputeScopeVisibleMessageStats authoritatively rebuilds the durable
// human-visible summary for one scope. It is intended for low-frequency repair
// paths such as rewind/delete/archive/restore where the visible set changed in
// a way that is not worth modeling as an incremental counter mutation.
func RecomputeScopeVisibleMessageStats(ctx context.Context, tx coredb.Tx, scopeID string, updatedAt time.Time) error {
	trimmedScopeID := strings.TrimSpace(scopeID)
	if trimmedScopeID == "" {
		return invalidArgument("scope id is required")
	}
	if updatedAt.IsZero() {
		updatedAt = time.Now().UTC()
	}
	result, err := tx.Exec(ctx, `
UPDATE scopes
SET visible_message_count = (SELECT COUNT(*) FROM scope_messages WHERE scope_id = $1 AND `+HumanVisibleMessageTypeSQL("scope_messages")+`),
    visible_last_message_at = (SELECT MAX(created_at) FROM scope_messages WHERE scope_id = $1 AND `+HumanVisibleMessageTypeSQL("scope_messages")+`),
    recent_author_member_ids = CASE
      WHEN type = 'thread' THEN (
        SELECT COALESCE(JSON_ARRAYAGG(recent.author_member_id), JSON_ARRAY())
        FROM (
          SELECT author_member_id, MAX(seq) AS latest_seq
          FROM scope_messages
          WHERE scope_id = $1
            AND `+ReplyThreadPreviewAuthorSQL("scope_messages")+`
          GROUP BY author_member_id
          ORDER BY latest_seq DESC
          LIMIT 5
        ) recent
      )
      ELSE recent_author_member_ids
    END,
    unread_rewind_generation = unread_rewind_generation + 1,
    updated_at = $2
WHERE id = $1
`, trimmedScopeID, updatedAt.UTC())
	if err != nil {
		return fmt.Errorf("recompute scope visible message stats: %w", err)
	}
	if result.RowsAffected() == 0 {
		var existing int64
		if err := tx.QueryRow(ctx, `
SELECT COUNT(1)
FROM scopes
WHERE id = $1
`, trimmedScopeID).Scan(&existing); err != nil {
			return fmt.Errorf("check recomputed scope exists: %w", err)
		}
		if existing > 0 {
			return nil
		}
		return notFound("scope not found")
	}
	return nil
}
