package service

import (
	"context"
	"fmt"
	"time"

	"github.com/CalmoAI/mcp-server-signoz/internal/domain"
)

// MCPService implements the MCPService interface
type MCPService struct {
	signozRepo domain.SignozRepository
	logger     domain.Logger
	tracer     domain.Tracer
	metrics    domain.Metrics
	cache      domain.Cache
}

// NewMCPService creates a new MCP service
func NewMCPService(
	signozRepo domain.SignozRepository,
	logger domain.Logger,
	tracer domain.Tracer,
	metrics domain.Metrics,
	cache domain.Cache,
) *MCPService {
	return &MCPService{
		signozRepo: signozRepo,
		logger:     logger,
		tracer:     tracer,
		metrics:    metrics,
		cache:      cache,
	}
}

// TestConnection implements MCPService interface
func (s *MCPService) TestConnection(ctx context.Context) (*domain.ConnectionStatus, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_test_connection")
	defer span.End()

	s.logger.Info("testing connection to Signoz",
		domain.Field{Key: "operation", Value: "signoz_test_connection"},
	)

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_test_connection"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_test_connection"})
	}()

	// Check cache first
	cacheKey := "connection_status"
	if s.cache != nil {
		if cached, err := s.cache.Get(ctx, cacheKey); err == nil {
			if status, ok := cached.(*domain.ConnectionStatus); ok {
				// Return cached status if it's recent (within 30 seconds)
				if time.Since(status.LastChecked) < 30*time.Second {
					s.logger.Debug("returning cached connection status")
					return status, nil
				}
			}
		}
	}

	// Test connection to Signoz
	status, err := s.signozRepo.TestConnection(ctx)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to test connection",
			domain.Field{Key: "error", Value: err.Error()},
		)
		return nil, fmt.Errorf("connection test failed: %w", err)
	}

	// Cache the result for 30 seconds
	if s.cache != nil {
		_ = s.cache.Set(ctx, cacheKey, status, 30*time.Second)
	}

	span.SetAttribute("connected", status.Connected)
	span.SetAttribute("latency_ms", float64(status.Latency.Milliseconds()))

	s.logger.Info("connection test completed",
		domain.Field{Key: "connected", Value: status.Connected},
		domain.Field{Key: "latency", Value: status.Latency.String()},
	)

	return status, nil
}

// FetchDashboards implements MCPService interface
func (s *MCPService) FetchDashboards(ctx context.Context) ([]domain.Dashboard, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_fetch_dashboards")
	defer span.End()

	s.logger.Info("fetching dashboards from Signoz",
		domain.Field{Key: "operation", Value: "signoz_fetch_dashboards"},
	)

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_fetch_dashboards"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_fetch_dashboards"})
	}()

	// Check cache first
	cacheKey := "dashboards"
	if s.cache != nil {
		if cached, err := s.cache.Get(ctx, cacheKey); err == nil {
			if dashboards, ok := cached.([]domain.Dashboard); ok {
				s.logger.Debug("returning cached dashboards",
					domain.Field{Key: "count", Value: len(dashboards)},
				)
				span.SetAttribute("cached", true)
				span.SetAttribute("dashboard_count", len(dashboards))
				return dashboards, nil
			}
		}
	}

	// Fetch dashboards from Signoz
	dashboards, err := s.signozRepo.GetDashboards(ctx)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to fetch dashboards",
			domain.Field{Key: "error", Value: err.Error()},
		)
		return nil, fmt.Errorf("failed to fetch dashboards: %w", err)
	}

	// Cache the result for 5 minutes
	if s.cache != nil {
		_ = s.cache.Set(ctx, cacheKey, dashboards, 5*time.Minute)
	}

	span.SetAttribute("cached", false)
	span.SetAttribute("dashboard_count", len(dashboards))

	s.logger.Info("successfully fetched dashboards",
		domain.Field{Key: "count", Value: len(dashboards)},
	)

	return dashboards, nil
}

// FetchDashboardDetails implements MCPService interface
func (s *MCPService) FetchDashboardDetails(ctx context.Context, dashboardID string) (*domain.Dashboard, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_fetch_dashboard_details")
	defer span.End()

	span.SetAttribute("dashboard_id", dashboardID)

	s.logger.Info("fetching dashboard details from Signoz",
		domain.Field{Key: "operation", Value: "signoz_fetch_dashboard_details"},
		domain.Field{Key: "dashboard_id", Value: dashboardID},
	)

	// Validate input
	if dashboardID == "" {
		err := fmt.Errorf("dashboard ID is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_fetch_dashboard_details"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_fetch_dashboard_details"})
	}()

	// Check cache first
	cacheKey := fmt.Sprintf("dashboard_details:%s", dashboardID)
	if s.cache != nil {
		if cached, err := s.cache.Get(ctx, cacheKey); err == nil {
			if dashboard, ok := cached.(*domain.Dashboard); ok {
				s.logger.Debug("returning cached dashboard details")
				span.SetAttribute("cached", true)
				return dashboard, nil
			}
		}
	}

	// Fetch dashboard details from Signoz
	dashboard, err := s.signozRepo.GetDashboardDetails(ctx, dashboardID)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to fetch dashboard details",
			domain.Field{Key: "error", Value: err.Error()},
			domain.Field{Key: "dashboard_id", Value: dashboardID},
		)
		return nil, fmt.Errorf("failed to fetch dashboard details: %w", err)
	}

	// Cache the result for 5 minutes
	if s.cache != nil {
		_ = s.cache.Set(ctx, cacheKey, dashboard, 5*time.Minute)
	}

	span.SetAttribute("cached", false)
	span.SetAttribute("panel_count", len(dashboard.Panels))

	s.logger.Info("successfully fetched dashboard details",
		domain.Field{Key: "dashboard_id", Value: dashboardID},
		domain.Field{Key: "panel_count", Value: len(dashboard.Panels)},
	)

	return dashboard, nil
}

// FetchDashboardData implements MCPService interface
func (s *MCPService) FetchDashboardData(ctx context.Context, dashboardName string, startTime, endTime time.Time) (*domain.DashboardData, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_fetch_dashboard_data")
	defer span.End()

	span.SetAttribute("dashboard_name", dashboardName)
	span.SetAttribute("start_time", startTime.Format(time.RFC3339))
	span.SetAttribute("end_time", endTime.Format(time.RFC3339))

	s.logger.Info("fetching dashboard data from Signoz",
		domain.Field{Key: "operation", Value: "signoz_fetch_dashboard_data"},
		domain.Field{Key: "dashboard_name", Value: dashboardName},
		domain.Field{Key: "start_time", Value: startTime.Format(time.RFC3339)},
		domain.Field{Key: "end_time", Value: endTime.Format(time.RFC3339)},
	)

	// Validate input
	if dashboardName == "" {
		err := fmt.Errorf("dashboard name is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if startTime.After(endTime) {
		err := fmt.Errorf("start time must be before end time")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_fetch_dashboard_data"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_fetch_dashboard_data"})
	}()

	timeRange := domain.TimeRange{
		Start: startTime,
		End:   endTime,
	}

	// Fetch dashboard data from Signoz
	data, err := s.signozRepo.GetDashboardData(ctx, dashboardName, timeRange)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to fetch dashboard data",
			domain.Field{Key: "error", Value: err.Error()},
			domain.Field{Key: "dashboard_name", Value: dashboardName},
		)
		return nil, fmt.Errorf("failed to fetch dashboard data: %w", err)
	}

	span.SetAttribute("panel_count", len(data.Panels))

	s.logger.Info("successfully fetched dashboard data",
		domain.Field{Key: "dashboard_name", Value: dashboardName},
		domain.Field{Key: "panel_count", Value: len(data.Panels)},
	)

	return data, nil
}

// FetchAPMMetrics implements MCPService interface
func (s *MCPService) FetchAPMMetrics(ctx context.Context, serviceName string, startTime, endTime time.Time) (*domain.APMMetrics, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_fetch_apm_metrics")
	defer span.End()

	span.SetAttribute("service_name", serviceName)
	span.SetAttribute("start_time", startTime.Format(time.RFC3339))
	span.SetAttribute("end_time", endTime.Format(time.RFC3339))

	s.logger.Info("fetching APM metrics from Signoz",
		domain.Field{Key: "operation", Value: "signoz_fetch_apm_metrics"},
		domain.Field{Key: "service_name", Value: serviceName},
		domain.Field{Key: "start_time", Value: startTime.Format(time.RFC3339)},
		domain.Field{Key: "end_time", Value: endTime.Format(time.RFC3339)},
	)

	// Validate input
	if serviceName == "" {
		err := fmt.Errorf("service name is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if startTime.After(endTime) {
		err := fmt.Errorf("start time must be before end time")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_fetch_apm_metrics"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_fetch_apm_metrics"})
	}()

	timeRange := domain.TimeRange{
		Start: startTime,
		End:   endTime,
	}

	// Check cache first
	cacheKey := fmt.Sprintf("apm_metrics:%s:%d:%d", serviceName, startTime.Unix(), endTime.Unix())
	if s.cache != nil {
		if cached, err := s.cache.Get(ctx, cacheKey); err == nil {
			if metrics, ok := cached.(*domain.APMMetrics); ok {
				s.logger.Debug("returning cached APM metrics")
				span.SetAttribute("cached", true)
				return metrics, nil
			}
		}
	}

	// Fetch APM metrics from Signoz
	metrics, err := s.signozRepo.GetAPMMetrics(ctx, serviceName, timeRange)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to fetch APM metrics",
			domain.Field{Key: "error", Value: err.Error()},
			domain.Field{Key: "service_name", Value: serviceName},
		)
		return nil, fmt.Errorf("failed to fetch APM metrics: %w", err)
	}

	// Cache the result for 2 minutes
	if s.cache != nil {
		_ = s.cache.Set(ctx, cacheKey, metrics, 2*time.Minute)
	}

	span.SetAttribute("cached", false)
	span.SetAttribute("metric_count", len(metrics.Metrics))

	s.logger.Info("successfully fetched APM metrics",
		domain.Field{Key: "service_name", Value: serviceName},
		domain.Field{Key: "metric_count", Value: len(metrics.Metrics)},
	)

	return metrics, nil
}

// FetchServices implements MCPService interface
func (s *MCPService) FetchServices(ctx context.Context, startTime, endTime *time.Time) ([]domain.Service, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_fetch_services")
	defer span.End()

	s.logger.Info("fetching services from Signoz",
		domain.Field{Key: "operation", Value: "signoz_fetch_services"},
	)

	if startTime != nil && endTime != nil {
		span.SetAttribute("start_time", startTime.Format(time.RFC3339))
		span.SetAttribute("end_time", endTime.Format(time.RFC3339))
		s.logger.Info("using time range filter",
			domain.Field{Key: "start_time", Value: startTime.Format(time.RFC3339)},
			domain.Field{Key: "end_time", Value: endTime.Format(time.RFC3339)},
		)

		if startTime.After(*endTime) {
			err := fmt.Errorf("start time must be before end time")
			span.SetStatus(domain.StatusCodeError, err.Error())
			s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
			return nil, err
		}
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_fetch_services"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_fetch_services"})
	}()

	var timeRange *domain.TimeRange
	if startTime != nil && endTime != nil {
		timeRange = &domain.TimeRange{
			Start: *startTime,
			End:   *endTime,
		}
	}

	// Check cache first
	cacheKey := "services"
	if timeRange != nil {
		cacheKey = fmt.Sprintf("services:%d:%d", timeRange.Start.Unix(), timeRange.End.Unix())
	}

	if s.cache != nil {
		if cached, err := s.cache.Get(ctx, cacheKey); err == nil {
			if services, ok := cached.([]domain.Service); ok {
				s.logger.Debug("returning cached services",
					domain.Field{Key: "count", Value: len(services)},
				)
				span.SetAttribute("cached", true)
				span.SetAttribute("service_count", len(services))
				return services, nil
			}
		}
	}

	// Fetch services from Signoz
	services, err := s.signozRepo.GetServices(ctx, timeRange)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to fetch services",
			domain.Field{Key: "error", Value: err.Error()},
		)
		return nil, fmt.Errorf("failed to fetch services: %w", err)
	}

	// Cache the result for 3 minutes
	if s.cache != nil {
		_ = s.cache.Set(ctx, cacheKey, services, 3*time.Minute)
	}

	span.SetAttribute("cached", false)
	span.SetAttribute("service_count", len(services))

	s.logger.Info("successfully fetched services",
		domain.Field{Key: "count", Value: len(services)},
	)

	return services, nil
}

// ExecuteClickHouseQuery implements MCPService interface
func (s *MCPService) ExecuteClickHouseQuery(ctx context.Context, sql string, startTime, endTime time.Time, params map[string]interface{}) (*domain.QueryResult, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_execute_clickhouse_query")
	defer span.End()

	span.SetAttribute("start_time", startTime.Format(time.RFC3339))
	span.SetAttribute("end_time", endTime.Format(time.RFC3339))

	s.logger.Info("executing ClickHouse query",
		domain.Field{Key: "operation", Value: "signoz_execute_clickhouse_query"},
		domain.Field{Key: "start_time", Value: startTime.Format(time.RFC3339)},
		domain.Field{Key: "end_time", Value: endTime.Format(time.RFC3339)},
	)

	// Validate input
	if sql == "" {
		err := fmt.Errorf("SQL query is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if startTime.After(endTime) {
		err := fmt.Errorf("start time must be before end time")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_execute_clickhouse_query"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_execute_clickhouse_query"})
	}()

	query := domain.ClickHouseQuery{
		SQL: sql,
		TimeRange: domain.TimeRange{
			Start: startTime,
			End:   endTime,
		},
		Params: params,
	}

	// Execute query
	result, err := s.signozRepo.ExecuteClickHouseQuery(ctx, query)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to execute ClickHouse query",
			domain.Field{Key: "error", Value: err.Error()},
		)
		return nil, fmt.Errorf("failed to execute ClickHouse query: %w", err)
	}

	span.SetAttribute("rows_returned", len(result.Rows))
	span.SetAttribute("execution_time_ms", float64(result.Meta.ExecutionTime.Milliseconds()))

	s.logger.Info("successfully executed ClickHouse query",
		domain.Field{Key: "rows_returned", Value: len(result.Rows)},
		domain.Field{Key: "execution_time", Value: result.Meta.ExecutionTime.String()},
	)

	return result, nil
}

// ExecuteBuilderQuery implements MCPService interface
func (s *MCPService) ExecuteBuilderQuery(ctx context.Context, queryType, metricName, aggregation string, filters []domain.QueryFilter, groupBy []string, startTime, endTime time.Time, step time.Duration, options map[string]interface{}) (*domain.QueryResult, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_execute_builder_query")
	defer span.End()

	span.SetAttribute("query_type", queryType)
	span.SetAttribute("metric_name", metricName)
	span.SetAttribute("aggregation", aggregation)
	span.SetAttribute("start_time", startTime.Format(time.RFC3339))
	span.SetAttribute("end_time", endTime.Format(time.RFC3339))

	s.logger.Info("executing builder query",
		domain.Field{Key: "operation", Value: "signoz_execute_builder_query"},
		domain.Field{Key: "query_type", Value: queryType},
		domain.Field{Key: "metric_name", Value: metricName},
		domain.Field{Key: "aggregation", Value: aggregation},
		domain.Field{Key: "start_time", Value: startTime.Format(time.RFC3339)},
		domain.Field{Key: "end_time", Value: endTime.Format(time.RFC3339)},
	)

	// Validate input
	if queryType == "" {
		err := fmt.Errorf("query type is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if metricName == "" {
		err := fmt.Errorf("metric name is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if startTime.After(endTime) {
		err := fmt.Errorf("start time must be before end time")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_execute_builder_query"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_execute_builder_query"})
	}()

	query := domain.BuilderQuery{
		QueryType:   queryType,
		MetricName:  metricName,
		Aggregation: aggregation,
		Filters:     filters,
		GroupBy:     groupBy,
		TimeRange: domain.TimeRange{
			Start: startTime,
			End:   endTime,
		},
		Step:    step,
		Options: options,
	}

	// Execute query
	result, err := s.signozRepo.ExecuteBuilderQuery(ctx, query)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to execute builder query",
			domain.Field{Key: "error", Value: err.Error()},
		)
		return nil, fmt.Errorf("failed to execute builder query: %w", err)
	}

	span.SetAttribute("rows_returned", len(result.Rows))
	span.SetAttribute("execution_time_ms", float64(result.Meta.ExecutionTime.Milliseconds()))

	s.logger.Info("successfully executed builder query",
		domain.Field{Key: "rows_returned", Value: len(result.Rows)},
		domain.Field{Key: "execution_time", Value: result.Meta.ExecutionTime.String()},
	)

	return result, nil
}

// FetchTracesOrLogs implements MCPService interface
func (s *MCPService) FetchTracesOrLogs(ctx context.Context, dataType string, startTime, endTime time.Time, serviceName string, limit int) ([]domain.TraceLog, error) {
	ctx, span := s.tracer.StartSpan(ctx, "mcp.signoz_fetch_traces_or_logs")
	defer span.End()

	span.SetAttribute("data_type", dataType)
	span.SetAttribute("service_name", serviceName)
	span.SetAttribute("start_time", startTime.Format(time.RFC3339))
	span.SetAttribute("end_time", endTime.Format(time.RFC3339))
	span.SetAttribute("limit", limit)

	s.logger.Info("fetching traces or logs from Signoz",
		domain.Field{Key: "operation", Value: "signoz_fetch_traces_or_logs"},
		domain.Field{Key: "data_type", Value: dataType},
		domain.Field{Key: "service_name", Value: serviceName},
		domain.Field{Key: "start_time", Value: startTime.Format(time.RFC3339)},
		domain.Field{Key: "end_time", Value: endTime.Format(time.RFC3339)},
		domain.Field{Key: "limit", Value: limit},
	)

	// Validate input
	if dataType != "traces" && dataType != "logs" {
		err := fmt.Errorf("data type must be 'traces' or 'logs'")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if serviceName == "" {
		err := fmt.Errorf("service name is required")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if startTime.After(endTime) {
		err := fmt.Errorf("start time must be before end time")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	if limit <= 0 || limit > 10000 {
		err := fmt.Errorf("limit must be between 1 and 10000")
		span.SetStatus(domain.StatusCodeError, err.Error())
		s.logger.Error("invalid input", domain.Field{Key: "error", Value: err.Error()})
		return nil, err
	}

	// Record metrics
	counter := s.metrics.Counter("mcp_tool_calls_total")
	counter.Add(ctx, 1, domain.Attribute{Key: "tool", Value: "signoz_fetch_traces_or_logs"})

	histogram := s.metrics.Histogram("mcp_tool_duration_seconds")
	start := time.Now()
	defer func() {
		duration := time.Since(start).Seconds()
		histogram.Record(ctx, duration, domain.Attribute{Key: "tool", Value: "signoz_fetch_traces_or_logs"})
	}()

	timeRange := domain.TimeRange{
		Start: startTime,
		End:   endTime,
	}

	// Fetch traces or logs from Signoz
	data, err := s.signozRepo.GetTracesOrLogs(ctx, dataType, timeRange, serviceName, limit)
	if err != nil {
		span.SetStatus(domain.StatusCodeError, err.Error())
		span.RecordError(err)
		s.logger.Error("failed to fetch traces or logs",
			domain.Field{Key: "error", Value: err.Error()},
			domain.Field{Key: "data_type", Value: dataType},
			domain.Field{Key: "service_name", Value: serviceName},
		)
		return nil, fmt.Errorf("failed to fetch %s: %w", dataType, err)
	}

	span.SetAttribute("records_returned", len(data))

	s.logger.Info("successfully fetched traces or logs",
		domain.Field{Key: "data_type", Value: dataType},
		domain.Field{Key: "service_name", Value: serviceName},
		domain.Field{Key: "records_returned", Value: len(data)},
	)

	return data, nil
}

// Ensure MCPService implements the MCPService interface
var _ domain.MCPService = (*MCPService)(nil)
