// Copyright 2018 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"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/google/subcommands"
	"go.chromium.org/luci/auth"
	"go.chromium.org/luci/auth/client/authcli"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/retry"
	"go.chromium.org/luci/common/retry/transient"
)

// FuchsiaUserAgent is used to set Fuchsia's User-Agent HTTP header for requests
// to the Catapult dashboard. The User-Agent header helps distinguish this
// uploader's entries from other entries in the Catapult logs. If left empty, Go
// inserts its own header "Go-http-client/XX" where XX is the version of the
// agent. The generic header makes our requests indistinguishable from other Go
// HTTP clients' requests.
const FuchsiaUserAgent = "Fuchsia-Uploader/1.0"

// UploadCommand uploads a data file to a URL when executed.
type UploadCommand struct {
	// The timeout for HTTP requests.
	timeout time.Duration

	// The URL to upload data to
	url string

	// LUCI flags used to parse command-line authentication options.
	authFlags authcli.Flags
}

func (*UploadCommand) Name() string {
	return "upload"
}

func (*UploadCommand) Usage() string {
	return "upload [options] json_file"
}

func (*UploadCommand) Synopsis() string {
	return "Uploads a JSON file to a URL"
}

func (cmd *UploadCommand) SetFlags(flags *flag.FlagSet) {
	// TODO(kjharland): For CI builders an --output flag that writes to an
	// output file would be a cleaner solution than writing to stdout and
	// having the caller stream or store the output. Add a flag for this
	// here.
	cmd.authFlags = authcli.Flags{}
	cmd.authFlags.Register(flags, auth.Options{})
	flags.DurationVar(&cmd.timeout, "timeout", 10*time.Second,
		"Request timeout duration string. e.g. 12s or 1m")
	flags.StringVar(&cmd.url, "url", "",
		"(required) The URL to upload to. Must have the format 'scheme://host[:port]'")
}

func (cmd *UploadCommand) Execute(ctx context.Context, f *flag.FlagSet, _ ...any) subcommands.ExitStatus {
	if f.NArg() < 1 {
		fmt.Fprintln(os.Stderr, "missing input file")
		return subcommands.ExitFailure
	}
	if f.NArg() != 1 {
		fmt.Fprintln(os.Stderr, "too many positional arguments")
		return subcommands.ExitFailure
	}
	if len(cmd.url) == 0 {
		fmt.Fprintln(os.Stderr, "url is required")
		return subcommands.ExitFailure
	}

	if cmd.timeout <= 0 {
		fmt.Fprintf(os.Stderr, "timeout must be positive. Got %s\n", cmd.timeout)
		return subcommands.ExitFailure
	}

	opts, err := cmd.authFlags.Options()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return subcommands.ExitFailure
	}

	inputFile := f.Arg(0)
	if err := uploadData(ctx, cmd.url, inputFile, cmd.timeout, opts); err != nil {
		logging.Errorf(ctx, "%s", err)
		return subcommands.ExitFailure
	}

	return subcommands.ExitSuccess
}

// CreateUploadRequest creates an HTTP request to upload the given data to the
// given catapultURL.
func CreateUploadRequest(catapultURL string, data string) (*http.Request, error) {
	// TODO(kjharland): Use a custom Flag variable to verify the URL instead of
	// a string.
	u, err := url.ParseRequestURI(catapultURL)
	if err != nil {
		return nil, fmt.Errorf("failed to parse url: %w", err)
	}
	if len(u.RawQuery) > 0 || len(u.Fragment) > 0 || (len(u.Path) > 0 && u.Path != "/") {
		return nil, fmt.Errorf(
			"url must have format: scheme://host[:port]. Got %s",
			u.String())
	}

	u.Path = "add_histograms"

	// URL encode the request body. This is weird but the Catapult dashboard
	// will reject the request because it expects a body of the form:
	// `data=url-encoded-histogramset` instead of the more usual JSON body:
	// `{data: ...}`.
	params := url.Values{}
	params.Set("data", data)
	content := params.Encode()

	req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(content))
	if err != nil {
		return nil, err
	}

	req.Header.Set("User-Agent", FuchsiaUserAgent)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Content-Length", strconv.Itoa(len(content)))

	return req, nil
}

func uploadData(ctx context.Context, catapultURL string, filepath string, timeout time.Duration, authOpts auth.Options) error {
	requestBody, err := os.ReadFile(filepath)
	if err != nil {
		return err
	}

	// Verify that the input data is actual JSON.  Ideally we'd verify the
	// structure of the data also but this isn't always practical. (For
	// example, when parsing a dynamic schema such as Catapult's
	// HistogramSet).
	// TODO(kjharland): use json.Valid after fuchsia's go is updated to v1.10
	var ignored any
	if err := json.Unmarshal(requestBody, &ignored); err != nil {
		return fmt.Errorf("input is not valid JSON: %w", err)
	}

	// The LUCI authenticator used to authenticate the request. Silent login
	// prevents an interactive login session when running from CI bots.
	authenticator := auth.NewAuthenticator(ctx, auth.SilentLogin, authOpts)
	client, err := authenticator.Client()
	if err != nil {
		return err
	}
	client.Timeout = timeout

	retryPolicy := transient.Only(func() retry.Iterator {
		return &retry.ExponentialBackoff{
			Limited: retry.Limited{
				Delay:   5 * time.Second,
				Retries: 3,
			},
			Multiplier: 2,
		}
	})
	return retry.Retry(ctx, retryPolicy, func() error {
		// client.Do mutates the request object so we must create a new request
		// for every attempt.
		req, err := CreateUploadRequest(catapultURL, string(requestBody))
		if err != nil {
			return fmt.Errorf("create request: %w", err)
		}
		response, err := client.Do(req)
		if err != nil {
			return err
		}
		// We don't need to use the body, but we must still read and close it to
		// ensure it's safe to reuse the same client if we retry.
		defer response.Body.Close()
		body, err := io.ReadAll(response.Body)
		if err != nil {
			return err
		}
		if len(body) > 0 {
			logging.Debugf(ctx, "Response from Catapult: %s", body)
		}
		if response.StatusCode < 200 || response.StatusCode >= 300 {
			logging.Warningf(ctx, "Got error from Catapult: %s", response.Status)
			err = errors.New(response.Status)
			if response.StatusCode >= 500 {
				err = transient.Tag.Apply(err)
			}
			return err
		}
		return nil
	}, nil)
}
