package query

import (
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"go.uber.org/zap"
)

// Gin context key set by diagnosis-query o11y JWT auth middleware.
const contextKeyGitHubUsername = "github_username"

func githubUsernameFromContext(c *gin.Context) string {
	if c == nil {
		return ""
	}
	return strings.TrimSpace(c.GetString(contextKeyGitHubUsername))
}

func logOlapQuerySubmitted(job *Job, dataset string, workGroup string) {
	if job == nil {
		return
	}
	recordOlapSubmitted(job)
	log.Info("olap query submitted",
		zap.String("github_username", job.GitHubUsername),
		zap.String("query_id", job.ID),
		zap.String("execution_id", job.ExecutionID),
		zap.String("engine", job.EngineName),
		zap.String("region", job.Region),
		zap.String("workgroup", workGroup),
		zap.String("dataset", dataset),
		zap.String("database", job.Database),
		zap.String("cluster_id", job.ClusterID),
		zap.String("tenant_id", job.TenantID),
		zap.String("output_mode", job.OutputMode),
		zap.String("sql", job.SQL),
		zap.String("effective_sql", job.EffectiveSQL),
	)
}

// logOlapQueryFinished emits Athena consumption for chargeback / per-user metering.
// Call once when a query first reaches a terminal state.
func logOlapQueryFinished(job *Job, st *ExecutionStatus, workGroup string) {
	if job == nil || st == nil {
		return
	}
	recordOlapFinished(job, st)
	fields := []zap.Field{
		zap.String("github_username", job.GitHubUsername),
		zap.String("query_id", job.ID),
		zap.String("execution_id", job.ExecutionID),
		zap.String("engine", job.EngineName),
		zap.String("region", job.Region),
		zap.String("workgroup", workGroup),
		zap.String("dataset", job.Dataset),
		zap.String("database", job.Database),
		zap.String("cluster_id", job.ClusterID),
		zap.String("tenant_id", job.TenantID),
		zap.String("output_mode", job.OutputMode),
		zap.String("status", st.Status),
		zap.Int64("scanned_bytes", st.ScannedBytes),
		zap.Int64("engine_execution_time_ms", st.EngineExecutionTimeMillis),
		zap.Int64("total_execution_time_ms", st.TotalExecutionTimeMillis),
		zap.Int64("queue_time_ms", st.QueryQueueTimeMillis),
		zap.Int64("planning_time_ms", st.QueryPlanningTimeMillis),
		zap.String("effective_sql", job.EffectiveSQL),
	}
	if st.StateChangeReason != "" {
		fields = append(fields, zap.String("state_change_reason", st.StateChangeReason))
	}
	log.Info("olap query finished", fields...)
}

func logOlapQueryResults(queryID string, page *Page) {
	if page == nil {
		return
	}
	log.Info("olap query results",
		zap.String("query_id", queryID),
		zap.Int("row_count", len(page.Rows)),
		zap.Int("column_count", len(page.Columns)),
		zap.Bool("has_more", page.NextToken != ""),
	)
}
