package cloudbuild

import (
	"context"
	"fmt"
	"strings"

	// Using v1 for triggers with special handling for GitLab
	cloudbuildv1 "google.golang.org/api/cloudbuild/v1"
	cloudbuildv2 "google.golang.org/api/cloudbuild/v2"
	"google.golang.org/api/googleapi"
)

// CreateTrigger creates a new build trigger in Cloud Build
// It creates a build trigger that will run when code is pushed to the specified branch
func (c *Client) CreateTrigger(projectID, location, name, repoName, branchPattern, buildConfigPath string, repoType, repoURI string) (*cloudbuildv1.BuildTrigger, error) {
	// We'll set up the basic fields for all trigger types, but the source configuration
	// (TriggerTemplate or GitFileSource) will be determined by repository type

	// Common fields for all trigger types
	triggerDescription := fmt.Sprintf("Trigger for %s on branch %s", repoName, branchPattern)

	// Use the provided repository URI if available
	repositoryURI := repoURI

	// Check if we can list any connections (but we don't filter by type anymore)
	_, err := c.ListConnections(projectID, location)
	if err != nil {
		fmt.Printf("Warning: Unable to list connections: %v\n", err)
	}

	// Try to get repository information from Cloud Build API
	repos, err := c.ListRepositoriesFromTriggerService(projectID, location)
	if err == nil && len(repos) > 0 {
		for _, repo := range repos {
			var simpleName string
			// Extract simple name from repo for comparison
			if repo.RemoteUri != "" {
				// Save the URI for later use in GitLab config
				repositoryURI = repo.RemoteUri

				uriParts := strings.Split(repo.RemoteUri, "/")
				if len(uriParts) > 0 {
					simpleName = strings.TrimSuffix(uriParts[len(uriParts)-1], ".git")
				}
			} else if repo.Name != "" {
				parts := strings.Split(repo.Name, "/")
				simpleName = parts[len(parts)-1]
			}

			// Check if this matches our target repository
			if simpleName == repoName {
				fmt.Printf("Found matching repository with URI: %s\n", repositoryURI)
				break
			}
		}
	}

	// Special case: for repository names starting with "github_" or containing an underscore
	// we assume they're standard Cloud Source Repositories
	if strings.HasPrefix(repoName, "github_") || strings.Contains(repoName, "_") {
		fmt.Println("Detected Cloud Source Repository based on name pattern")
	}

	// Create a trigger based on repository type
	fmt.Printf("Setting up trigger for repository: %s\n", repoName)

	// IMPORTANT: We must create a clean trigger object with ONLY the relevant source configuration
	// The CloudBuild API does not allow both TriggerTemplate and GitFileSource to be set
	// Configure the trigger differently based on the repository type
	var trigger *cloudbuildv1.BuildTrigger

	if strings.ToUpper(repoType) == "GITLAB" {
		// For GitLab repositories, we need to use GitFileSource with the correct configuration
		fmt.Println("Configuring trigger for GitLab repository with enhanced settings")

		// Make sure we have a valid repository URI
		if repositoryURI == "" {
			return nil, fmt.Errorf("repository URI is required for GitLab triggers but was empty")
		}

		// Extract host URI from full repository URI if needed
		uriParts := strings.Split(repositoryURI, "/")
		var hostUri string
		if len(uriParts) >= 3 {
			// Format should be https://gitlab.domain.com
			hostUri = uriParts[0] + "//" + uriParts[2]
			fmt.Printf("Using GitLab host URI: %s\n", hostUri)
		}

		// Create the proper GitLab trigger configuration
		trigger = &cloudbuildv1.BuildTrigger{
			Name:        name,
			Description: triggerDescription,
			// Important: For GitLab, DO NOT set Filename here as it conflicts with GitFileSource.Path
			Disabled: false,
		}

		// Set the GitFileSource configuration for GitLab
		trigger.GitFileSource = &cloudbuildv1.GitFileSource{
			Path:     buildConfigPath,
			Uri:      repositoryURI,
			Revision: branchPattern,
			RepoType: "GITLAB", // Ensure this is uppercase
		}

		// Check if we need to add other fields for GitLab configuration
		// Add debug information
		fmt.Printf("GitLab Trigger Details:\n")
		fmt.Printf("  Repository URI: %s\n", repositoryURI)
		fmt.Printf("  Branch/Revision: %s\n", branchPattern)
		fmt.Printf("  Config Path: %s\n", buildConfigPath)
	} else {
		// For GitHub and Cloud Source Repositories, use TriggerTemplate
		fmt.Println("Configuring trigger for GitHub/CSR repository")
		trigger = &cloudbuildv1.BuildTrigger{
			Name:        name,
			Description: triggerDescription,
			Filename:    buildConfigPath,
			Disabled:    false,
			TriggerTemplate: &cloudbuildv1.RepoSource{
				ProjectId:  projectID,
				RepoName:   repoName,
				BranchName: branchPattern,
			},
		}
	}

	// Log the configuration
	fmt.Printf("Repository: %s, Branch: %s, Type: %s\n", repoName, branchPattern, repoType)

	// Log the final trigger configuration for debugging
	fmt.Println("\nFinal trigger configuration:")
	if trigger.TriggerTemplate != nil {
		fmt.Printf("Using TriggerTemplate with repository: %s, branch: %s\n",
			trigger.TriggerTemplate.RepoName, trigger.TriggerTemplate.BranchName)
	} else if trigger.GitFileSource != nil {
		fmt.Printf("Using GitFileSource with URI: %s, revision: %s, repo type: %s\n",
			trigger.GitFileSource.Uri, trigger.GitFileSource.Revision, trigger.GitFileSource.RepoType)
	}

	// Create a v1 service for trigger operations
	ctx := context.Background()
	// Use the same credentials that were used for the v2 service
	v1Service, err := cloudbuildv1.NewService(ctx)
	if err != nil {
		return nil, fmt.Errorf("error creating Cloud Build v1 service: %w", err)
	}

	// Add verbose diagnostics about what we're about to send to the API
	fmt.Println("\n=== TRIGGER CREATION DIAGNOSTICS ===")
	fmt.Printf("ProjectID: %s\n", projectID)
	fmt.Printf("Location: %s (note: v1 API ignores this)\n", location)
	fmt.Printf("Trigger Name: %s\n", trigger.Name)
	fmt.Printf("Description: %s\n", trigger.Description)
	fmt.Printf("Build Config Path: %s\n", buildConfigPath)
	if trigger.TriggerTemplate != nil {
		fmt.Println("Using TriggerTemplate configuration:")
		fmt.Printf("  - Project ID: %s\n", trigger.TriggerTemplate.ProjectId)
		fmt.Printf("  - Repository: %s\n", trigger.TriggerTemplate.RepoName)
		fmt.Printf("  - Branch: %s\n", trigger.TriggerTemplate.BranchName)
		if trigger.TriggerTemplate.Dir != "" {
			fmt.Printf("  - Directory: %s\n", trigger.TriggerTemplate.Dir)
		}
	} else if trigger.GitFileSource != nil {
		fmt.Println("Using GitFileSource configuration:")
		fmt.Printf("  - Repository URI: %s\n", trigger.GitFileSource.Uri)
		fmt.Printf("  - Repository Type: %s\n", trigger.GitFileSource.RepoType)
		fmt.Printf("  - Revision: %s\n", trigger.GitFileSource.Revision)
		fmt.Printf("  - Build Config Path: %s\n", trigger.GitFileSource.Path)
	}

	// Make the API call to create the trigger
	// Note: In v1 API, triggers are created at the project level, not location
	fmt.Println("\nAttempting API call to create trigger...")
	resp, err := v1Service.Projects.Triggers.Create(projectID, trigger).Do()
	if err != nil {
		fmt.Println("\n=== ERROR DETAILS ===")
		fmt.Printf("Error type: %T\n", err)
		fmt.Printf("Full error: %v\n", err)

		// Check if it's a Google API error, which gives us more details
		if gerr, ok := err.(*googleapi.Error); ok {
			fmt.Printf("HTTP Status: %d\n", gerr.Code)
			fmt.Printf("Error Message: %s\n", gerr.Message)

			if len(gerr.Errors) > 0 {
				fmt.Println("Error details:")
				for i, e := range gerr.Errors {
					fmt.Printf("  %d. Reason: %s, Message: %s\n", i+1, e.Reason, e.Message)
				}
			}
		}

		// Suggest a solution based on the error
		fmt.Println("\n=== SUGGESTED RESOLUTION ===")
		fmt.Println("1. Verify the repository exists in your Google Cloud project")
		fmt.Println("2. Check that the service account has permission to create triggers")
		fmt.Println("3. Try creating a trigger manually in the console to verify project configuration")
		fmt.Println("4. For GitLab repositories, ensure the Secret Manager permissions are correct")

		return nil, fmt.Errorf("error creating trigger: %w", err)
	}

	return resp, nil
}

// ListTriggers lists all triggers in the specified project
// Note: In v1 API, triggers are at the project level, not location
func (c *Client) ListTriggers(projectID, location string) ([]*cloudbuildv1.BuildTrigger, error) {
	// Create a v1 service for trigger operations
	ctx := context.Background()
	// Use the same credentials that were used for the v2 service
	v1Service, err := cloudbuildv1.NewService(ctx)
	if err != nil {
		return nil, fmt.Errorf("error creating Cloud Build v1 service: %w", err)
	}

	// Make the API call to list triggers
	// Note: location parameter is ignored since v1 API doesn't support it
	resp, err := v1Service.Projects.Triggers.List(projectID).Do()
	if err != nil {
		return nil, fmt.Errorf("error listing triggers: %w", err)
	}

	return resp.Triggers, nil
}

// ListRepositoriesFromTriggerService lists repositories that can be used for triggers
func (c *Client) ListRepositoriesFromTriggerService(projectID, location string) ([]*cloudbuildv2.Repository, error) {
	// Format is just for log messages as we'll fetch repositories through connections
	_ = fmt.Sprintf("projects/%s/locations/%s", projectID, location)

	// First, get all connections to list repositories from each
	connections, err := c.ListConnections(projectID, location)
	if err != nil {
		return nil, fmt.Errorf("error listing connections: %w", err)
	}

	// Collect repositories from all connections
	var allRepositories []*cloudbuildv2.Repository

	// For each connection, list its repositories
	for _, conn := range connections {
		// Extract the connection name from the full resource name
		parts := strings.Split(conn.Name, "/")
		if len(parts) < 6 {
			continue // Invalid format, skip
		}
		connName := parts[len(parts)-1]

		// Get repositories for this connection
		repos, err := c.ListLinkableRepositories(projectID, location, connName)
		if err != nil {
			// Log the error but continue with other connections
			fmt.Printf("Warning: Error listing repositories for connection %s: %v\n", connName, err)
			continue
		}

		// Add to our collection
		allRepositories = append(allRepositories, repos...)
	}

	return allRepositories, nil
}

// GetTrigger retrieves an existing trigger from Cloud Build
func (c *Client) GetTrigger(projectID, location, name string) (*cloudbuildv1.BuildTrigger, error) {
	// Create a v1 service for trigger operations
	ctx := context.Background()
	// Use the same credentials that were used for the v2 service
	v1Service, err := cloudbuildv1.NewService(ctx)
	if err != nil {
		return nil, fmt.Errorf("error creating Cloud Build v1 service: %w", err)
	}

	// Make the API call to get the trigger
	// Note: location parameter is ignored since v1 API doesn't support it
	resp, err := v1Service.Projects.Triggers.Get(projectID, name).Do()
	if err != nil {
		return nil, fmt.Errorf("error getting trigger: %w", err)
	}

	return resp, nil
}

// DeleteTrigger deletes an existing trigger from Cloud Build
func (c *Client) DeleteTrigger(projectID, location, name string) error {
	// Create a v1 service for trigger operations
	ctx := context.Background()
	// Use the same credentials that were used for the v2 service
	v1Service, err := cloudbuildv1.NewService(ctx)
	if err != nil {
		return fmt.Errorf("error creating Cloud Build v1 service: %w", err)
	}

	// Make the API call to delete the trigger
	// Note: location parameter is ignored since v1 API doesn't support it
	_, err = v1Service.Projects.Triggers.Delete(projectID, name).Do()
	if err != nil {
		return fmt.Errorf("error deleting trigger: %w", err)
	}

	return nil
}
