// Copyright 2023 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"
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/maruel/subcommands"
	"go.chromium.org/luci/auth"
	"go.chromium.org/luci/luciexe/build"
	ftxproto "go.fuchsia.dev/infra/cmd/ftxtest/proto"
)

func cmdRun(authOpts auth.Options) *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "run",
		ShortDesc: "runs test",
		LongDesc:  "Runs test based on luciexe protocol.",
		CommandRun: func() subcommands.CommandRun {
			r := &runImpl{}
			r.Init(authOpts)
			return r
		},
	}
}

type runImpl struct {
	commonFlags

	subcommands.CommandRunBase
}

func (r *runImpl) Init(defaultAuthOpts auth.Options) {
	r.commonFlags.Init(defaultAuthOpts)
}

func (r *runImpl) Run(a subcommands.Application, args []string, env subcommands.Env) int {
	if err := r.commonFlags.Parse(); err != nil {
		fmt.Fprintf(os.Stderr, "Error parsing common flags: %v\n", err)
		return 1
	}
	r.luciexeInit()
	// luciexe uses os.exit to exit.
	return 0
}

func (r *runImpl) luciexeInit() {
	buildInput := &ftxproto.InputProperties{}
	buildOutput := &ftxproto.OutputProperties{}
	var writeOutputProps func(*ftxproto.OutputProperties)
	build.Main(buildInput, &writeOutputProps, nil, func(bbCtx context.Context, extraArgs []string, state *build.State) error {
		state.SetSummaryMarkdown(buildInput.Name)
		ctx := context.Background()
		defer writeOutputProps(buildOutput)
		swarming, err := r.authenticateStep(ctx, bbCtx, buildInput)
		if err != nil {
			err = fmt.Errorf("authenticateStep: %v", err)
			state.SetSummaryMarkdown(fmt.Sprintf("%v: %v", buildInput.Name, err))
			return err
		}
		taskId, err := r.launchTaskStep(bbCtx, swarming, buildInput, state)
		if err != nil {
			err = fmt.Errorf("launchTaskStep: %v", err)
			state.SetSummaryMarkdown(fmt.Sprintf("%v: %v", buildInput.Name, err))
			return err
		}
		if err := r.linksStep(bbCtx, buildInput, taskId); err != nil {
			err = fmt.Errorf("linksStep: %v", err)
			state.SetSummaryMarkdown(fmt.Sprintf("%v: %v", buildInput.Name, err))
			return err
		}
		if err := r.waitTaskStep(bbCtx, swarming, taskId); err != nil {
			err = fmt.Errorf("waitTaskStep: %v", err)
			state.SetSummaryMarkdown(fmt.Sprintf("%v: %v", buildInput.Name, err))
			return err
		}
		if err := r.resultStep(ctx, bbCtx, swarming, taskId, buildOutput); err != nil {
			err = fmt.Errorf("resultStep: %v", err)
			state.SetSummaryMarkdown(fmt.Sprintf("%v: %v", buildInput.Name, err))
			return err
		}
		return nil
	})
}

func (r *runImpl) authenticateStep(ctx context.Context, bbCtx context.Context, buildInput *ftxproto.InputProperties) (*Swarming, error) {
	step, bbCtx := build.StartStep(bbCtx, "Authenticate")
	authenticator := auth.NewAuthenticator(ctx, auth.SilentLogin, r.parsedAuthOpts)
	httpClient, err := authenticator.Client()
	if err != nil {
		fmt.Fprintf(os.Stderr, "You need to login first by running:\n")
		fmt.Fprintf(os.Stderr, "  luci-auth login -scopes %q\n", strings.Join(r.parsedAuthOpts.Scopes, " "))
		return nil, errors.New("Not logged in.")
	}
	cas, err := NewCAS(ctx, r.parsedAuthOpts, instance(buildInput))
	if err != nil {
		return nil, fmt.Errorf("NewCAS: %v", err)
	}
	swarming, err := NewSwarming(httpClient, instance(buildInput), cas)
	if err != nil {
		step.End(err)
		return nil, fmt.Errorf("NewSwarming: %v", err)
	}
	step.End(nil)
	return swarming, nil
}

func (r *runImpl) launchTaskStep(bbCtx context.Context, swarming *Swarming, buildInput *ftxproto.InputProperties, state *build.State) (string, error) {
	step, bbCtx := build.StartStep(bbCtx, "Launch Swarming Task")
	if len(buildInput.Name) == 0 {
		err := errors.New("Name is required.")
		step.End(err)
		return "", err
	}
	parentTaskId := ""
	if state.Build() != nil && state.Build().Infra != nil && state.Build().Infra.Swarming != nil {
		parentTaskId = state.Build().Infra.Swarming.TaskId
	}
	task, err := swarming.LaunchTask(buildInput, parentTaskId)
	if err != nil {
		step.End(err)
		return "", fmt.Errorf("LaunchTask: %v", err)
	}
	step.End(nil)
	return task.TaskId, nil
}

func (r *runImpl) linksStep(bbCtx context.Context, buildInput *ftxproto.InputProperties, taskId string) error {
	step, bbCtx := build.StartStep(bbCtx, "Links")
	md := fmt.Sprintf("* [swarming task](https://%s.appspot.com/task?id=%s)", instance(buildInput), taskId)
	if spongeId, ok := buildInput.Metadata["GUITAR_SPONGE_ID"]; ok {
		md = fmt.Sprintf("%s\n* [sponge](http://sponge/%s)", md, spongeId)
	}
	step.SetSummaryMarkdown(md)
	step.End(nil)
	return nil
}

func (r *runImpl) waitTaskStep(bbCtx context.Context, swarming *Swarming, taskId string) error {
	step, bbCtx := build.StartStep(bbCtx, "Wait Task Completion")
	if err := swarming.WaitTask(taskId); err != nil {
		step.End(err)
		return err
	}
	step.End(nil)
	return nil
}

func (r *runImpl) resultStep(ctx context.Context, bbCtx context.Context, swarming *Swarming, taskId string, buildOutput *ftxproto.OutputProperties) error {
	step, bbCtx := build.StartStep(bbCtx, "Result")
	if err := swarming.CheckTestFailure(ctx, taskId, buildOutput); err != nil {
		step.End(err)
		return err
	}
	step.End(nil)
	return nil
}

func instance(buildInput *ftxproto.InputProperties) string {
	if buildInput.External {
		return "chromium-swarm"
	} else {
		return "chrome-swarming"
	}
}
