package main

import (
	"flag"
	"fmt"
	"log"
	"net/url"

	"github.com/OctopusDeploy/go-octopusdeploy/octopusdeploy"
	"github.com/pkg/errors"
)

func main() {
	var (
		apiKey                   string
		octopusURL               string
		spaceID                  string
		projectGroup             string
		releaseNotesTemplate     string
		overrideExistingTemplate bool
	)

	flag.StringVar(&apiKey, "apiKey", "", "Path to the file with the configuration")
	flag.StringVar(&octopusURL, "octopusURL", "https://octopus.delphi.zone", "Path to OpenVPN sacli")
	flag.StringVar(&spaceID, "spaceID", "", "Space ID, default one will be used if skipped")
	flag.StringVar(&projectGroup, "projectGroup", "delphi", "Project group to apply new template to")
	flag.StringVar(&releaseNotesTemplate, "releaseNotesTemplate", "#{each package in Octopus.Release.Package}\n- #{package.PackageId} #{package.Version}\n#{each workItem in package.WorkItems}\n    - [#{workItem.Id}](#{workItem.LinkUrl}) - #{workItem.Description}\n#{/each}\n#{/each}", "Release notes template")
	flag.BoolVar(&overrideExistingTemplate, "overrideExistingTemplate", false, "Apply changes even if release notes template already exists in the project")
	flag.Parse()

	if apiKey == "" {
		log.Fatal("No apiKey has been specified")
	}
	apiURL, err := url.Parse(octopusURL)
	if err != nil {
		log.Fatalf("error parsing URL for Octopus API: %v", err)
	}

	client, err := octopusdeploy.NewClient(nil, apiURL, apiKey, spaceID)
	if err != nil {
		log.Fatalf("error creating API client: %v", err)
	}

	// get project by its ID
	projects, err := getProjectsByPGName(client, projectGroup)
	if err != nil {
		log.Fatal(err)
	}

	for _, project := range projects {
		log.Printf("Project name %s, template '%s'", project.Name, project.ReleaseNotesTemplate)
		if overrideExistingTemplate || project.ReleaseNotesTemplate == "" {
			project.ReleaseNotesTemplate = releaseNotesTemplate
			// update project
			updatedProject, err := client.Projects.Update(project)
			if err != nil {
				log.Fatalf("error updating project: %v", err)
			}

			log.Printf("project updated: %s (%s)\n", updatedProject.Name, updatedProject.GetModifiedOn())
		} else {
			log.Printf("project has been skipped: (%s)\n", project.Name)
		}
	}

}

func getProjectsByPGName(client *octopusdeploy.Client, projectGroup string) ([]*octopusdeploy.Project, error) {
	projectGroups, err := client.ProjectGroups.GetByPartialName(projectGroup)
	if err != nil {
		return nil, errors.Wrap(err, "Error getting project group")
	}
	//Filter out only group that has exactly the same name
	var projectGroupID = ""
	for _, pg := range projectGroups {
		if pg.Name == projectGroup {
			projectGroupID = pg.ID
		}
	}
	if err != nil {
		return nil, errors.New(fmt.Sprintf("No project groups with given name have been found: %v", projectGroup))
	}

	//Get all projects and filter them out by project group id
	var projects []*octopusdeploy.Project
	allProjects, err := client.Projects.GetAll()
	if err != nil {
		return nil, errors.Wrap(err, "Error getting projects")
	}
	for _, project := range allProjects {
		if project.ProjectGroupID == projectGroupID {
			projects = append(projects, project)
		}
	}

	return projects, nil
}
