// Copyright 2023 The Go 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 upload

import (
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"path/filepath"
	"runtime/debug"
	"strings"
	"time"

	"golang.org/x/telemetry/internal/configstore"
	"golang.org/x/telemetry/internal/telemetry"
)

// RunConfig configures non-default behavior of a call to Run.
//
// All fields are optional, for testing or observability.
type RunConfig struct {
	TelemetryDir string    // if set, overrides the telemetry data directory
	UploadURL    string    // if set, overrides the telemetry upload endpoint
	LogWriter    io.Writer // if set, used for detailed logging of the upload process
	Env          []string  // if set, appended to the config download environment
	StartTime    time.Time // if set, overrides the upload start time
}

// Run generates and uploads reports, as allowed by the mode file.
func Run(config RunConfig) error {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("upload recover: %v", err)
		}
	}()
	uploader, err := newUploader(config)
	if err != nil {
		return err
	}
	defer uploader.Close()
	return uploader.Run()
}

// uploader encapsulates a single upload operation, carrying parameters and
// shared state.
type uploader struct {
	// config is used to select counters to upload.
	config        *telemetry.UploadConfig //
	configVersion string                  // version of the config
	dir           telemetry.Dir           // the telemetry dir to process

	uploadServerURL string
	startTime       time.Time

	cache parsedCache

	logFile *os.File
	logger  *log.Logger
}

// newUploader creates a new uploader to use for running the upload for the
// given config.
//
// Uploaders should only be used for one call to [uploader.Run].
func newUploader(rcfg RunConfig) (*uploader, error) {
	// Determine the upload directory.
	var dir telemetry.Dir
	if rcfg.TelemetryDir != "" {
		dir = telemetry.NewDir(rcfg.TelemetryDir)
	} else {
		dir = telemetry.Default
	}

	// Determine the upload URL.
	uploadURL := rcfg.UploadURL
	if uploadURL == "" {
		uploadURL = "https://telemetry.go.dev/upload"
	}

	// Determine the upload logger.
	//
	// This depends on the provided rcfg.LogWriter and the presence of
	// dir.DebugDir, as follows:
	//  1. If LogWriter is present, log to it.
	//  2. If DebugDir is present, log to a file within it.
	//  3. If both LogWriter and DebugDir are present, log to a multi writer.
	//  4. If neither LogWriter nor DebugDir are present, log to a noop logger.
	var logWriters []io.Writer
	logFile, err := debugLogFile(dir.DebugDir())
	if err != nil {
		logFile = nil
	}
	if logFile != nil {
		logWriters = append(logWriters, logFile)
	}
	if rcfg.LogWriter != nil {
		logWriters = append(logWriters, rcfg.LogWriter)
	}
	var logWriter io.Writer
	switch len(logWriters) {
	case 0:
		logWriter = io.Discard
	case 1:
		logWriter = logWriters[0]
	default:
		logWriter = io.MultiWriter(logWriters...)
	}
	logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile)

	// Fetch the upload config, if it is not provided.
	var (
		config        *telemetry.UploadConfig
		configVersion string
	)

	if mode, _ := dir.Mode(); mode == "on" {
		// golang/go#68946: only download the upload config if it will be used.
		//
		// TODO(rfindley): This is a narrow change aimed at minimally fixing the
		// associated bug. In the future, we should read the mode only once during
		// the upload process.
		config, configVersion, err = configstore.Download("latest", rcfg.Env)
		if err != nil {
			return nil, err
		}
	} else {
		config = &telemetry.UploadConfig{}
		configVersion = "v0.0.0-0"
	}

	// Set the start time, if it is not provided.
	startTime := time.Now().UTC()
	if !rcfg.StartTime.IsZero() {
		startTime = rcfg.StartTime
	}

	return &uploader{
		config:          config,
		configVersion:   configVersion,
		dir:             dir,
		uploadServerURL: uploadURL,
		startTime:       startTime,

		logFile: logFile,
		logger:  logger,
	}, nil
}

// Close cleans up any resources associated with the uploader.
func (u *uploader) Close() error {
	if u.logFile == nil {
		return nil
	}
	return u.logFile.Close()
}

// Run generates and uploads reports
func (u *uploader) Run() error {
	if telemetry.DisabledOnPlatform {
		return nil
	}
	todo := u.findWork()
	ready, err := u.reports(&todo)
	if err != nil {
		u.logger.Printf("Error building reports: %v", err)
		return fmt.Errorf("reports failed: %v", err)
	}
	u.logger.Printf("Uploading %d reports", len(ready))
	for _, f := range ready {
		u.uploadReport(f)
	}
	return nil
}

// debugLogFile arranges to write a log file in the given debug directory, if
// it exists.
func debugLogFile(debugDir string) (*os.File, error) {
	fd, err := os.Stat(debugDir)
	if os.IsNotExist(err) {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	if !fd.IsDir() {
		return nil, fmt.Errorf("debug path %q is not a directory", debugDir)
	}
	info, ok := debug.ReadBuildInfo()
	if !ok {
		return nil, fmt.Errorf("no build info")
	}
	year, month, day := time.Now().UTC().Date()
	goVers := info.GoVersion
	// E.g.,  goVers:"go1.22-20240109-RC01 cl/597041403 +dcbe772469 X:loopvar"
	words := strings.Fields(goVers)
	goVers = words[0]
	progPkgPath := info.Path
	if progPkgPath == "" {
		progPkgPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe")
	}
	prog := path.Base(progPkgPath)
	progVers := info.Main.Version
	if progVers == "(devel)" { // avoid special characters in created file names
		progVers = "devel"
	}
	logBase := strings.ReplaceAll(
		fmt.Sprintf("%s-%s-%s-%4d%02d%02d-%d.log", prog, progVers, goVers, year, month, day, os.Getpid()),
		" ", "")
	fname := filepath.Join(debugDir, logBase)
	if _, err := os.Stat(fname); err == nil {
		// This process previously called upload.Run
		return nil, nil
	}
	f, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
	if err != nil {
		if os.IsExist(err) {
			return nil, nil // this process previously called upload.Run
		}
		return nil, err
	}
	return f, nil
}
