package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"regexp"
	"time"

	"code.justin.tv/dta/twitch-create-service/internal/bootstrap"
	"code.justin.tv/dta/twitch-create-service/internal/grafana"
	"code.justin.tv/twitch/cli/config"
)

var (
	nameRegexp *regexp.Regexp
)

func init() {
	nameRegexp = regexp.MustCompile(`(\w/)?\w`)
	rand.Seed(time.Now().UTC().UnixNano())
}

func main() {
	name := flag.String("name", "", "repository name. use org/name format to make it a non-user repo")
	delete := flag.Bool("delete", false, "delete the repo if it already exists")
	verbose := flag.Bool("v", false, "enable debug output")
	appType := flag.String("type", "go_http", "type of app to generate. options: go_http, ruby_http, ruby_grpc")
	tempDirRoot := flag.String("temp-dir-root", "", "Temporary workspace to perform service generation. Will create a folder prefixed with \"twitch-create-service\" at this location. "+
		"Default or \"\" will use system temporary directory.")
	skipProvision := flag.Bool("skip-provision", false, "set to skip terraform provisioning. still generates terraform rules. (useful for non-web AWS accounts)")
	org := flag.String("aws-org", "web", "twitch organization. determines which AWS accounts are used during provisioning. options: web, video")
	skipDashboard := flag.Bool("skip-dashboard", false, "set to skip grafana provisioning")
	grafanaToken := flag.String("grafana-token", "eyJrIjoibmtuTFVudmg0eTdlb2VMNTBtYk14dzI5TjZjOGx2dmciLCJuIjoiVHdpdGNoIENyZWF0ZSBTZXJ2aWNlIiwiaWQiOjF9", "authorization token for creating grafana dashboard")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Generate and deploy a production-ready internal API service\n\n")
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.Parse()

	if *name == "" {
		log.Fatal("name is required")
	}

	if !nameRegexp.MatchString(*name) {
		log.Fatalf("%v is not a valid repository name", *name)
	}

	config, err := config.Read()
	if err != nil {
		log.Fatal(err)
	}
	user := config.Github.Username
	token := config.Github.Token

	log.Print("Running preflight dependency check")
	err = bootstrap.PreflightCheck(*skipProvision, *org)
	if err != nil {
		log.Fatal(err)
	}

	tmpRoot, err := prepTmp(*tempDirRoot)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Created temporary directory at %v\n", tmpRoot)

	repo, err := bootstrap.InitializeRepository(*appType, *name, *user, *token, tmpRoot, *delete, *verbose)
	if err != nil {
		log.Fatal(err)
	}

	err = repo.DefineInfrastructure(*user, *org)
	if err != nil {
		log.Fatal(err)
	}

	var host string
	if !*skipProvision {
		host, err = repo.Provision(*user, *token, tmpRoot, *org)
		if err != nil {
			log.Fatal(err)
		}
	}

	if !*skipDashboard {
		err = grafana.CreateDashboard(repo.Owner(), repo.Name(), *appType, *grafanaToken, bootstrap.AWSAccounts[*org]["production"])
		if err != nil {
			log.Fatal(err)
		}
	}

	if host != "" {
		fmt.Printf("\nYour service is ready at http://%v\n", host)
	}

	fmt.Println("\nNext steps:")
	fmt.Printf("\n1. Start coding!\n\tgit clone https://git-aws.internal.justin.tv/%v.git\n", repo.FullName())
	fmt.Printf("\n2. Deploy your changes\n\thttps://clean-deploy.internal.justin.tv/#/%v\n", repo.FullName())
	fmt.Printf("\n3. Monitor your service\n\thttps://grafana.internal.justin.tv/dashboard/db/%v\n", repo.Name())
	fmt.Println("\n4. Play some Dota 2")
	fmt.Println("")
}

func prepTmp(tempDirRoot string) (string, error) {
	tmpRoot := "" // Default directory parameter. Not directly using tempDirRoot to avoid chance of accidentally deleting.
	var err error

	tmpRoot, err = ioutil.TempDir(tempDirRoot, "twitch-create-service")
	if err != nil {
		return "", fmt.Errorf("Error creating temporary directory: %v", err)
	}

	tmpRootAbsolute, err := filepath.EvalSymlinks(tmpRoot)
	if err != nil {
		return "", fmt.Errorf("Error evalulating absolute path from path %v: %v\n", tmpRoot, err)
	}
	tmpRoot = tmpRootAbsolute

	return tmpRoot, nil
}
