package job

import (
	"context"
	"fmt"
	"strings"

	"github.com/shiningrush/fastflow/pkg/mod"
	"github.com/spf13/cobra"
	consolev1 "github.com/tidbcloud/metrics-integration/global/api/integration/v1"
	"github.com/tidbcloud/metrics-integration/global/internal/domain/controller/integration"
	"github.com/tidbcloud/metrics-integration/global/internal/domain/entity"
	"github.com/tidbcloud/metrics-integration/global/internal/infrastructure/di"
	"github.com/tidbcloud/metrics-integration/global/pkg/cvt"
	"gorm.io/gorm"
)

// IntegrationReq holds configuration for integration operations
type IntegrationReq struct {
	PipelineID      uint64
	OrgID           uint64
	ProjectID       uint64
	ClusterID       uint64
	IntegrationType string
	DatadogAPIKey   string
	DatadogSite     string
	NewrelicAPIKey  string
	NewrelicSite    string
}

// parseIntegrationType converts string to IntegrationType enum
func parseIntegrationType(typeStr string) (consolev1.IntegrationType, error) {
	switch strings.ToLower(typeStr) {
	case "datadog":
		return consolev1.IntegrationType_INTEGRATION_TYPE_DATADOG, nil
	case "newrelic":
		return consolev1.IntegrationType_INTEGRATION_TYPE_NEWRELIC, nil
	default:
		return consolev1.IntegrationType_INTEGRATION_TYPE_UNSPECIFIED,
			fmt.Errorf("unsupported integration type: %s. Supported types: datadog, newrelic", typeStr)
	}
}

// parseDatadogSite converts string to DatadogSite enum
func parseDatadogSite(siteStr string) (entity.DatadogSite, error) {
	switch strings.ToLower(siteStr) {
	case "us1":
		return entity.DatadogSiteUS1, nil
	case "us3":
		return entity.DatadogSiteUS3, nil
	case "us5":
		return entity.DatadogSiteUS5, nil
	case "eu1":
		return entity.DatadogSiteEU1, nil
	case "us1-fed":
		return entity.DatadogSiteUS1FED, nil
	case "ap1":
		return entity.DatadogSiteAP1, nil
	default:
		return entity.DatadogSiteUnspecified,
			fmt.Errorf("unsupported datadog site: %s. Supported sites: us1, us3, us5, eu1, us1-fed, ap1", siteStr)
	}
}

// parseNewrelicSite converts string to NewrelicSite enum
func parseNewrelicSite(siteStr string) (entity.NewrelicSite, error) {
	switch strings.ToLower(siteStr) {
	case "us-otlp":
		return entity.NewrelicSiteUSOTLP, nil
	case "eu-otlp":
		return entity.NewrelicSiteEUOTLP, nil
	default:
		return entity.NewrelicSiteUnspecified,
			fmt.Errorf("unsupported newrelic site: %s. Supported sites: us-otlp, eu-otlp", siteStr)
	}
}

func mustMarkFlagRequired(cmd *cobra.Command, flagNames ...string) {
	for _, flagName := range flagNames {
		if err := cmd.MarkFlagRequired(flagName); err != nil {
			panic(err)
		}
	}
}

// createIntegrationCommand creates the integration creation command
func createIntegrationCommand() *cobra.Command {
	var req IntegrationReq

	cmd := &cobra.Command{
		Use:   "create",
		Short: "Create a new integration (Datadog or NewRelic) for a cluster",
		Long: `Create a new integration for monitoring metrics, logs, or traces.
		
This command creates an integration with external monitoring services like Datadog or NewRelic.
The integration will be validated and configured for the specified cluster.`,
		Example: `  # Create Datadog integration
  job integration create --org-id 1 --project-id 1 --cluster-id 1 \
    --type datadog \
    --datadog-api-key "your-datadog-api-key" --datadog-site us1

  # Create NewRelic integration
  job integration create --org-id 1 --project-id 1 --cluster-id 1 \
    --type newrelic \
    --newrelic-api-key "your-newrelic-api-key" --newrelic-site us-otlp`,
		RunE: func(cmd *cobra.Command, args []string) error {
			ctx := context.Background()

			if req.OrgID == 0 || req.ProjectID == 0 || req.ClusterID == 0 {
				return fmt.Errorf("org-id, project-id, and cluster-id are required")
			}

			integrationType, err := parseIntegrationType(req.IntegrationType)
			if err != nil {
				return err
			}

			var ddMaskedKey, nrMaskedKey string
			var ddUrl, ddDashboardUrl, nrUrl, nrDashboardUrl string

			switch integrationType {
			case consolev1.IntegrationType_INTEGRATION_TYPE_DATADOG:
				if req.DatadogAPIKey == "" {
					return fmt.Errorf("datadog-api-key is required for Datadog integration")
				}

				datadogSite, err := parseDatadogSite(req.DatadogSite)
				if err != nil {
					return err
				}

				fmt.Println("Validating Datadog API key...")
				valid, err := integration.ValidateDatadogAPIKey(ctx, req.DatadogAPIKey, datadogSite)
				if err != nil {
					return fmt.Errorf("error validating datadog api key: %w", err)
				}
				if !valid {
					return fmt.Errorf("invalid datadog api key")
				}

				fmt.Println("Creating Datadog integration...")
				integrationResp, err := integration.CreateDatadogIntegration(
					ctx,
					entity.ID(req.ClusterID),
					datadogSite,
					req.DatadogAPIKey,
					// TODO: input creator info
					"system",
				)
				if err != nil {
					return fmt.Errorf("error creating datadog integration: %w", err)
				}
				ddMaskedKey = integrationResp.MaskedDatadogApiKey

				ddUrl = cvt.GetDatadogSiteUrl(datadogSite)
				ddDashboardUrl = cvt.GetDatadogDashboardUrl(datadogSite)

			case consolev1.IntegrationType_INTEGRATION_TYPE_NEWRELIC:
				if req.NewrelicAPIKey == "" {
					return fmt.Errorf("newrelic-api-key is required for NewRelic integration")
				}

				newrelicSite, err := parseNewrelicSite(req.NewrelicSite)
				if err != nil {
					return err
				}

				fmt.Println("Validating NewRelic API key...")
				valid, err := integration.ValidateNewrelicAPIKey(ctx, req.NewrelicAPIKey, newrelicSite)
				if err != nil {
					return fmt.Errorf("error validating newrelic api key: %w", err)
				}
				if !valid {
					return fmt.Errorf("invalid newrelic api key")
				}

				fmt.Println("Creating NewRelic integration...")
				integrationResp, err := integration.CreateNewrelicIntegration(
					ctx,
					entity.ID(req.ClusterID),
					newrelicSite,
					req.NewrelicAPIKey,
					// TODO: input creator info
					"system",
				)
				if err != nil {
					return fmt.Errorf("error creating newrelic integration: %w", err)
				}
				nrMaskedKey = integrationResp.MaskedNewrelicApiKey

				nrUrl = cvt.GetNewrelicSiteEndpoint(newrelicSite)
				nrDashboardUrl = cvt.GetNewrelicSiteDashboard(newrelicSite)

			default:
				return fmt.Errorf("unsupported integration type")
			}

			fmt.Println("\n✅ Integration created successfully!")
			fmt.Printf("🏢 Org ID: %d\n", req.OrgID)
			fmt.Printf("📁 Project ID: %d\n", req.ProjectID)
			fmt.Printf("🔗 Cluster ID: %d\n", req.ClusterID)
			fmt.Printf("🔧 Type: %s\n", req.IntegrationType)

			if ddMaskedKey != "" {
				fmt.Printf("\n🐕 Datadog Integration Details:\n")
				fmt.Printf("  🔑 Masked API Key: %s\n", ddMaskedKey)
				fmt.Printf("  🌍 Site: %s\n", req.DatadogSite)
				fmt.Printf("  🔗 URL: %s\n", ddUrl)
				fmt.Printf("  📊 Dashboard: %s\n", ddDashboardUrl)
			}

			if nrMaskedKey != "" {
				fmt.Printf("\n🔵 NewRelic Integration Details:\n")
				fmt.Printf("  🔑 Masked API Key: %s\n", nrMaskedKey)
				fmt.Printf("  🌍 Site: %s\n", req.NewrelicSite)
				fmt.Printf("  🔗 URL: %s\n", nrUrl)
				fmt.Printf("  📊 Dashboard: %s\n", nrDashboardUrl)
			}

			return nil
		},
	}

	cmd.Flags().Uint64Var(&req.OrgID, "org-id", 0, "Organization ID (required)")
	cmd.Flags().Uint64Var(&req.ProjectID, "project-id", 0, "Project ID (required)")
	cmd.Flags().Uint64Var(&req.ClusterID, "cluster-id", 0, "Cluster ID (required)")
	cmd.Flags().StringVar(&req.IntegrationType, "type", "", "Integration type: datadog, newrelic (required)")
	cmd.Flags().StringVar(&req.DatadogAPIKey, "datadog-api-key", "", "Datadog API key (required for Datadog integration)")
	cmd.Flags().StringVar(&req.DatadogSite, "datadog-site", "us1", "Datadog site: us1, us3, us5, eu1, us1-fed, ap1")
	cmd.Flags().StringVar(&req.NewrelicAPIKey, "newrelic-api-key", "", "NewRelic API key (required for NewRelic integration)")
	cmd.Flags().StringVar(&req.NewrelicSite, "newrelic-site", "us-otlp", "NewRelic site: us-otlp, eu-otlp")

	mustMarkFlagRequired(cmd, "org-id", "project-id", "cluster-id", "type")

	return cmd
}

// deleteIntegrationCommand creates the integration deletion command
func deleteIntegrationCommand() *cobra.Command {
	var req IntegrationReq

	cmd := &cobra.Command{
		Use:   "delete",
		Short: "Delete an existing integration for a cluster",
		Long: `Delete an existing integration for a cluster.
		
This command removes an integration configuration and stops data collection
for the specified integration type.`,
		Example: `  # Delete Datadog integration
  job integration delete --pipeline-id 1`,
		RunE: func(cmd *cobra.Command, args []string) error {
			ctx := context.Background()

			if req.PipelineID == 0 {
				return fmt.Errorf("pipline-id are required")
			}

			var pipeline entity.Integration

			integrationType, err := parseIntegrationType(req.IntegrationType)
			if err != nil {
				return err
			}

			if err := di.DiCall(func(db *gorm.DB) error {
				query := db.First(&entity.Integration{}).Where("id = ?", req.PipelineID)
				return query.Find(&pipeline).Error
			}); err != nil {
				return fmt.Errorf("get pipeline failed: %v", err)
			}

			fmt.Printf("Deleting %s integration for cluster %d...\n", req.IntegrationType, req.ClusterID)
			s, err := integration.DisableIntegrationofCluster(ctx, entity.ID(req.ClusterID), cvt.TypeConsoleAPIToDB(integrationType))
			if err != nil {
				return fmt.Errorf("error deleting integration: %w", err)
			}

			fmt.Println("\n✅ Integration deleted successfully!")
			fmt.Printf("📊 Status: %s\n", s.String())
			fmt.Printf("🏢 Org ID: %d\n", req.OrgID)
			fmt.Printf("📁 Project ID: %d\n", req.ProjectID)
			fmt.Printf("🔗 Cluster ID: %d\n", req.ClusterID)
			fmt.Printf("🔧 Type: %s\n", req.IntegrationType)

			return nil
		},
	}

	cmd.Flags().Uint64Var(&req.PipelineID, "pipeline-id", 0, "Pipeline ID (required)")

	mustMarkFlagRequired(cmd, "pipeline-id")

	return cmd
}

// listIntegrationCommand creates the integration listing command
func listIntegrationCommand() *cobra.Command {
	var req IntegrationReq

	cmd := &cobra.Command{
		Use:   "list",
		Short: "List all integrations for a cluster",
		Long: `List all integrations configured for a cluster.
		
This command displays all active integrations and their current status.`,
		Example: `  # List all integrations for a cluster
  job integration list --cluster-id 1

  # List only Datadog integrations
  job integration list --cluster-id 1 --type datadog`,
		RunE: func(cmd *cobra.Command, args []string) error {
			ctx := context.Background()

			if req.ClusterID == 0 {
				return fmt.Errorf("cluster-id is required")
			}

			var integrationType consolev1.IntegrationType = consolev1.IntegrationType_INTEGRATION_TYPE_UNSPECIFIED
			if req.IntegrationType != "" {
				var err error
				integrationType, err = parseIntegrationType(req.IntegrationType)
				if err != nil {
					return err
				}
			}

			fmt.Printf("Listing integrations for cluster %d...\n", req.ClusterID)
			integrations, err := integration.ListIntegrationsForConsoleAPI(ctx, req.ClusterID, cvt.TypeConsoleAPIToDB(integrationType))
			if err != nil {
				return fmt.Errorf("error listing integrations: %w", err)
			}

			if len(integrations) == 0 {
				fmt.Println("No integrations found for this cluster.")
				return nil
			}

			fmt.Printf("\n📋 Found %d integration(s):\n\n", len(integrations))

			for i, integration := range integrations {
				fmt.Printf("Integration %d:\n", i+1)
				fmt.Printf("  🏢 Org ID: %d\n", integration.OrgId)
				fmt.Printf("  📁 Project ID: %d\n", integration.ProjectId)
				fmt.Printf("  🔗 Cluster ID: %d\n", integration.ClusterId)
				fmt.Printf("  🔧 Type: %s\n", integration.Type.String())
				fmt.Printf("  📊 Status: %s\n", integration.Status.String())

				if integration.StatusReason != "" {
					fmt.Printf("  ⚠️  Status Reason: %s\n", integration.StatusReason)
				}

				// 显示负载类型
				if len(integration.Payloads) > 0 {
					payloadStrs := make([]string, len(integration.Payloads))
					for j, payload := range integration.Payloads {
						payloadStrs[j] = payload.String()
					}
					fmt.Printf("  📦 Payloads: %s\n", strings.Join(payloadStrs, ", "))
				}

				// 显示 Datadog 信息
				if integration.Type == consolev1.IntegrationType_INTEGRATION_TYPE_DATADOG {
					fmt.Printf("  🐕 Datadog Details:\n")
					if integration.DatadogMaskedApiKey != "" {
						fmt.Printf("    🔑 Masked API Key: %s\n", integration.DatadogMaskedApiKey)
					}
					if integration.DatadogSite != consolev1.DatadogSite_DATADOG_SITE_UNSPECIFIED {
						fmt.Printf("    🌍 Site: %s\n", integration.DatadogSite.String())
					}
					if integration.DatadogSiteUrl != "" {
						fmt.Printf("    🔗 URL: %s\n", integration.DatadogSiteUrl)
					}
					if integration.DatadogDashboardUrl != "" {
						fmt.Printf("    📊 Dashboard: %s\n", integration.DatadogDashboardUrl)
					}
				}

				// 显示 NewRelic 信息
				if integration.Type == consolev1.IntegrationType_INTEGRATION_TYPE_NEWRELIC {
					fmt.Printf("  🔵 NewRelic Details:\n")
					if integration.NewrelicMaskedApiKey != "" {
						fmt.Printf("    🔑 Masked API Key: %s\n", integration.NewrelicMaskedApiKey)
					}
					if integration.NewrelicSite != consolev1.NewrelicSite_NEWRELIC_SITE_UNSPECIFIED {
						fmt.Printf("    🌍 Site: %s\n", integration.NewrelicSite.String())
					}
					if integration.NewrelicSiteUrl != "" {
						fmt.Printf("    🔗 URL: %s\n", integration.NewrelicSiteUrl)
					}
					if integration.NewrelicDashboardUrl != "" {
						fmt.Printf("    📊 Dashboard: %s\n", integration.NewrelicDashboardUrl)
					}
				}

				fmt.Println()
			}

			return nil
		},
	}

	cmd.Flags().Uint64Var(&req.ClusterID, "cluster-id", 0, "Cluster ID (required)")
	cmd.Flags().StringVar(&req.IntegrationType, "type", "", "Integration type filter: datadog, newrelic (optional)")

	mustMarkFlagRequired(cmd, "cluster-id")

	return cmd
}

// cleanIntegrationCommand creates the command to clean integration resources
func cleanIntegrationCommand() *cobra.Command {
	var req IntegrationReq

	cmd := &cobra.Command{
		Use:   "clean-integration",
		Short: "Clean integration resources for a pipeline",
		Long:  `Clean integrations resources for a pipeline.`,
		Example: `  # Clean paused integrations for a pipeline
  job integration clean-integration --pipeline-id 1`,
		RunE: func(cmd *cobra.Command, args []string) error {
			if req.PipelineID == 0 {
				return fmt.Errorf("pipeline-id is required")
			}

			fmt.Printf("Cleaning paused integrations for pipeline %d...\n", req.PipelineID)
			var integrations []entity.Integration
			if err := di.DiCall(func(db *gorm.DB) error {
				return db.Unscoped().Model(&entity.Integration{}).
					Where("id = ?", req.PipelineID).
					Find(&integrations).Error
			}); err != nil {
				return fmt.Errorf("failed to query integrations: %w", err)
			}

			if len(integrations) == 0 {
				fmt.Println("No paused integrations found for this pipeline.")
				return nil
			}

			for _, integration := range integrations {
				if err := di.DiCall(func() error {
					// skip db deletion
					if _, err := mod.GetCommander().RunDagWithTags("delete-pipeline", map[string]string{
						"id":               fmt.Sprintf("%d", integration.ID),
						"skip_db_deletion": "true",
					}, map[string]string{}); err != nil {
						return fmt.Errorf("failed to delete integration pipeline: %w", err)
					}
					return nil
				}); err != nil {
					fmt.Printf("Failed to delete integration %d: %v\n", integration.ID, err)
					continue
				}

				fmt.Printf("Successfully deleted integration %d\n", integration.ID)
			}

			fmt.Println("\n✅ All paused integrations cleaned successfully!")
			return nil
		},
	}

	cmd.Flags().Uint64Var(&req.PipelineID, "pipeline-id", 0, "Pipeline ID (required)")
	mustMarkFlagRequired(cmd, "pipeline-id")

	return cmd
}

// registerIntegrationJobFunc registers all integration-related commands
func registerIntegrationJobFunc(cmd *cobra.Command) {
	cmd.AddCommand(createIntegrationCommand())
	cmd.AddCommand(redeployIntegrationCommand())
	cmd.AddCommand(redeployRegionCommand())
	cmd.AddCommand(deleteIntegrationCommand())
	cmd.AddCommand(listIntegrationCommand())
	cmd.AddCommand(cleanIntegrationCommand())
}

func init() {
	integrationCmd := &cobra.Command{
		Use:   "integration",
		Short: "Manage integrations for monitoring services (Datadog, NewRelic)",
		Long: `Manage integrations for external monitoring services.
		
This command allows you to create, delete, and list integrations with
monitoring services like Datadog and NewRelic for your clusters.

Supported integration types:
- Datadog: Monitor metrics, logs, and traces
- NewRelic: Monitor metrics, logs, and traces

Supported payload types:
- metrics: Collect and forward metrics data
- logs: Collect and forward log data  
- traces: Collect and forward trace data`,
		Example: `  # Create a Datadog integration
  job integration create --org-id 1 --project-id 1 --cluster-id 1 \
    --type datadog --payloads metrics \
    --datadog-api-key "your-api-key" --datadog-site us1

  # List all integrations
  job integration list --cluster-id 1
  
  # Delete an integration
  job integration delete --org-id 1 --project-id 1 --cluster-id 1 --type datadog`,
		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			return nil
		},
	}

	// register integration commands
	registerIntegrationJobFunc(integrationCmd)

	jobCmd.AddCommand(integrationCmd)
}
