// 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"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/google/subcommands"
	"go.chromium.org/luci/auth"
	"go.chromium.org/luci/auth/client/authcli"
)

// 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, _ ...interface{}) 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 %v\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 {
		fmt.Fprintln(os.Stderr, 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: %v", 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 := ioutil.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 interface{}
	if err := json.Unmarshal(requestBody, &ignored); err != nil {
		return fmt.Errorf("input is not valid JSON: %v", err)
	}

	req, err := CreateUploadRequest(catapultURL, string(requestBody))
	if err != nil {
		return fmt.Errorf("create request: %v", err.Error())
	}

	// 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

	// TODO(kjharland): Add retry functionality here.
	response, err := client.Do(req)
	if err != nil {
		return err
	}

	if response.StatusCode < 200 || response.StatusCode >= 300 {
		return errors.New(response.Status)
	}

	log.Println(response.Status)
	return nil
}
