package common

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"

	l4g "github.com/alecthomas/log4go"
)

// GCPConnectInstance use gcloud tools connects to a GCP instance and runs a remote command
// TODO: Should be use gcloud ssh command to connect to the instance instead of using ssh command
func GCPConnectInstance(instanceName, zone, project, remoteCommand string) {
	// Connect to the instance using gcloud
	connectCmd := exec.Command("gcloud", "compute", "ssh", instanceName, "--zone", zone, "--project", project, "--command", remoteCommand)

	err := connectCmd.Run()
	if err != nil {
		l4g.Error("Error running gcloud connect command: %v", err)
		return
	}

	l4g.Info("Connected instance %s, remote command %s completed.", instanceName, remoteCommand)

	// Disconnect from the instance
	disconnectCmd := exec.Command("gcloud", "compute", "ssh", instanceName, "--zone", zone, "--command", "exit")

	err = disconnectCmd.Run()
	if err != nil {
		l4g.Error("Error running gcloud disconnect command: %v", err)
		return
	}

	l4g.Info("Disconnected from the instance %s.", instanceName)
}

func delVpcPeering(ec2Host, cerPath, loginUser, vpcName, network string) {
	cmd := fmt.Sprintf("gcloud compute networks peerings delete %s --network=%s", vpcName, network)
	l4g.Info("delVpcPeering cmd is %s", cmd)
	ConnectInstance(ec2Host, cerPath, loginUser, cmd)
}

func createVpcPeering(ec2Host, cerPath, loginUser, vpcName, network, peerProject, peerNetwork string) {
	cmd := fmt.Sprintf("gcloud compute networks peerings create %s --network %s --peer-project %s "+
		"--peer-network %s --auto-create-routes", vpcName, network, peerProject, peerNetwork)
	l4g.Info("createVpcPeering cmd is %s", cmd)
	ConnectInstance(ec2Host, cerPath, loginUser, cmd)
}

func startInstance(ec2Host, cerPath, loginUser, instanceName string) string {
	cmd := fmt.Sprintf("gcloud compute instances start %s", instanceName)
	l4g.Info("startInstance cmd is %s", cmd)
	string1, _ := ConnectInstance(ec2Host, cerPath, loginUser, cmd)
	list := strings.Fields(string1)
	l4g.Info("gcp ip is: %s", list[len(list)-1])
	return list[len(list)-1]
}

func stopInstance(ec2Host, cerPath, loginUser, instanceName string) {
	cmd := fmt.Sprintf("gcloud compute instances stop %s", instanceName)
	l4g.Info("stopInstance cmd is %s", cmd)
	ConnectInstance(ec2Host, cerPath, loginUser, cmd)
}

func PutGcpBucketPolicy(bucketname, role_arn, ec2Host, cerPath, loginUser string) error {
	s3cmd := fmt.Sprintf("gsutil iam ch serviceAccount:%s:roles/storage.admin %s", role_arn, bucketname)
	l4g.Info("gcscmd is : %s", s3cmd)
	output, flag := ConnectInstance(ec2Host, cerPath, loginUser, s3cmd)
	if flag != true {
		return fmt.Errorf(output)
	}
	return nil
}

func DeleteBucket(bucketname, ec2Host, cerPath, loginUser string) error {
	s3cmd := fmt.Sprintf("gsutil rm -r %s", bucketname)
	l4g.Info("gsutil is : %s", s3cmd)
	output, flag := ConnectInstance(ec2Host, cerPath, loginUser, s3cmd)
	if flag != true {
		return fmt.Errorf(output)
	}
	return nil
}

func CreateBucket(bucketname, ec2Host, cerPath, loginUser string) error {
	s3cmd := fmt.Sprintf("gsutil mb -l us-west1 %s", bucketname)
	l4g.Info("gsutil is : %s", s3cmd)
	output, flag := ConnectInstance(ec2Host, cerPath, loginUser, s3cmd)
	if flag != true {
		return fmt.Errorf(output)
	}
	return nil
}

func GetBucketSize(bucketname, ec2Host, cerPath, loginUser string) (float64, error) {
	s3cmd := fmt.Sprintf("gsutil du -s %s", bucketname)
	l4g.Info("gsutil is : %s", s3cmd)
	data, result := ConnectInstance(ec2Host, cerPath, loginUser, s3cmd)
	if result == false {
		return 0, fmt.Errorf(data)
	}
	dataList := strings.Split(data, " ")
	size, err := strconv.ParseFloat(dataList[0], 64)
	if err != nil {
		l4g.Error("strconv.ParseFloat failed:%s", err)
		return 0, fmt.Errorf("strconv.ParseFloat failed:%s", err)
	}
	return size, nil
}
