// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"context"
	"os"
	"path/filepath"

	"go.chromium.org/luci/common/clock"

	"github.com/golang/protobuf/ptypes/timestamp"

	"go.chromium.org/luci/luciexe/exe"
	"go.chromium.org/luci/luciexe/invoke"
	"go.fuchsia.dev/infra/cmd/build_init/checkout"

	"go.chromium.org/luci/logdog/common/types"

	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
	"go.chromium.org/luci/logdog/client/butlerlib/bootstrap"
)

const (
	// Root dir to ensure recipe bundle CIPD package.
	cipdRoot = "rb"

	// Default integration ref to fetch, if not passed through build properties.
	defaultIntegrationRef = "HEAD"

	// Top-level step name for a bootstrapped recipe execution.
	namespace = "bootstrapped_recipe"

	// Recipe manifest filename relative to root of an integration checkout.
	recipesManifest = "infra/recipes"

	// Recipe bundle CIPD package name to use.
	recipesPackageName = "fuchsia/infra/recipe_bundles/fuchsia.googlesource.com/infra/recipes"
)

type bootstrapStepRunner struct {
	build     *buildbucketpb.Build
	send      exe.BuildSender
	bootstrap *bootstrap.Bootstrap
}

// Calls a named step func, and attaches the step to sr.Build.Steps.
func (sr *bootstrapStepRunner) runStep(ctx context.Context, name string, fn stepFunc) error {
	start := clock.Now(ctx).Unix()
	err := fn(ctx, sr.build)
	end := clock.Now(ctx).Unix()

	// If there is an error, mark the step purple and attach a stderr log.
	var status buildbucketpb.Status
	logs := []*buildbucketpb.Log{}
	if err != nil {
		status = buildbucketpb.Status_INFRA_FAILURE
		log, logErr := sr.getStderrLog(ctx, name, err)
		if logErr != nil {
			return logErr
		}
		logs = append(logs, log)
	} else {
		status = buildbucketpb.Status_SUCCESS
	}

	step := buildbucketpb.Step{
		Name:      name,
		StartTime: &timestamp.Timestamp{Seconds: start},
		EndTime:   &timestamp.Timestamp{Seconds: end},
		Status:    status,
		Logs:      logs,
	}
	sr.build.Steps = append(sr.build.Steps, &step)
	sr.send()
	return err
}

// Calls a luciexe, attaching its steps to sr.Build.Steps.
func (sr *bootstrapStepRunner) invoke(ctx context.Context, exePath string, opts *invoke.Options) error {
	subprocess, err := invoke.Start(ctx, exePath, sr.build, opts)
	if err != nil {
		return err
	}
	// Add recipe execution steps to the build.
	sr.build.Steps = append(sr.build.Steps, subprocess.Step)
	sr.send()
	_, err = subprocess.Wait()
	return err
}

// Writes a step error to a LogDog stream and returns a Log.
func (sr *bootstrapStepRunner) getStderrLog(ctx context.Context, name string, stepErr error) (*buildbucketpb.Log, error) {
	streamName, err := types.MakeStreamName("", name, "stderr")
	if err != nil {
		return nil, err
	}
	wc, err := sr.bootstrap.Client.NewTextStream(ctx, streamName)
	defer wc.Close()
	if err != nil {
		return nil, err
	}
	if _, err := wc.Write([]byte(stepErr.Error())); err != nil {
		return nil, err
	}
	streamAddr := types.StreamAddr{
		Host:    sr.bootstrap.CoordinatorHost,
		Project: sr.bootstrap.Project,
		Path:    sr.bootstrap.Prefix.AsPathPrefix(streamName),
	}
	log := buildbucketpb.Log{
		Name: "stderr",
		Url:  streamAddr.String(),
	}
	return &log, nil
}

// A stepFunc which resolves an integration checkout.
func resolveCheckout(ctx context.Context, build *buildbucketpb.Build) error {
	integrationURL, err := resolveIntegrationURL(build.Input)
	if err != nil {
		return err
	}
	return checkout.Checkout(*build.Input, *integrationURL, defaultIntegrationRef)
}

// A stepFunc which resolves the recipes version in a checkout and downloads the bundle.
func resolveRecipeBundle(ctx context.Context, build *buildbucketpb.Build) error {
	manifestXML, err := os.Open(recipesManifest)
	if err != nil {
		return err
	}
	defer manifestXML.Close()
	pkg, err := resolveRecipesPackage(manifestXML)
	if err != nil {
		return err
	}
	return ensure(ctx, pkg, cipdRoot)
}

// BootstrapRecipe resolves the recipes version to use, downloads
// the recipe bundle from CIPD, and uses the bundle to run the build.
func bootstrapRecipe(ctx context.Context, sr stepRunner) error {
	if err := sr.runStep(ctx, "resolve checkout", resolveCheckout); err != nil {
		return err
	}
	if err := sr.runStep(ctx, "resolve recipe bundle", resolveRecipeBundle); err != nil {
		return err
	}
	invokeOpts := invoke.Options{Namespace: namespace}
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}
	luciexePath := filepath.Join(cwd, cipdRoot, "luciexe")
	// Invoke recipe bundle luciexe.
	if err := sr.invoke(ctx, luciexePath, &invokeOpts); err != nil {
		return err
	}
	return nil
}

func main() {
	exe.Run(func(ctx context.Context, build *buildbucketpb.Build, send exe.BuildSender) error {
		logdogBootstrap, err := bootstrap.Get()
		if err != nil {
			return err
		}
		return bootstrapRecipe(ctx, &bootstrapStepRunner{
			build:     build,
			send:      send,
			bootstrap: logdogBootstrap,
		})
	})
}
