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

// 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) {
	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 data to")
}

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
}

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).
	if !json.Valid(requestBody) {
		return errors.New("input is not valid JSON")
	}

	// 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", string(requestBody))
	content := params.Encode()

	req, err := http.NewRequest(http.MethodPost, catapultURL, strings.NewReader(content))
	if err != nil {
		return fmt.Errorf("create request: %v", err.Error())
	}
	// 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.
	// This is indistinguishable from other Go http clients.
	req.Header.Set("User-Agent", "Fuchsia-Uploader/1.0")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Content-Length", strconv.Itoa(len(content)))

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

	// Generate the OAuth token used to authenticate the request.
	oauthToken, err := authenticator.GetAccessToken(time.Minute)
	if err != nil {
		return fmt.Errorf("create token: %v", err.Error())
	}

	// Set an auth header on the request, containing the token generated from the
	// provided service account information.
	oauthToken.SetAuthHeader(req)

	client, err := authenticator.Client()
	if err != nil {
		return err
	}
	client.Timeout = timeout

	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
}
