// Copyright 2022 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 omaha_tool

import (
	"bufio"
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"time"

	"go.fuchsia.dev/fuchsia/tools/lib/color"
	"go.fuchsia.dev/fuchsia/tools/lib/logger"
)

type OmahaToolArgs struct {
	ToolPath       string
	PrivateKeyId   string
	PrivateKeyPath string
	AppId          string
	LocalHostname  string
	RequireCup     bool
}

type responseAndMetadata struct {
	// Note: Keep this struct up-to-date with ResponseAndMetadata within
	// mock-omaha-server/src/lib.rs
	Response        string `json:"response,omitempty"`
	Merkle          string `json:"merkle,omitempty"`
	CheckAssertion  string `json:"check_assertion,omitempty"`
	Version         string `json:"version,omitempty"`
	CohortAssertion string `json:"cohort_assertion,omitempty"`
	Codebase        string `json:"codebase,omitempty"`
	PackagePath     string `json:"package_path,omitempty"`
}

type OmahaTool struct {
	Args      OmahaToolArgs
	port      string
	serverURL string
	cmd       *exec.Cmd
	stdoutBuf *bytes.Buffer
}

func NewOmahaServer(ctx context.Context, args OmahaToolArgs, providedStdout io.Writer, providedStderr io.Writer) (*OmahaTool, error) {
	l := logger.NewLogger(
		logger.DebugLevel,
		color.NewColor(color.ColorAuto),
		os.Stdout,
		os.Stderr,
		"omaha-server: ")
	l.SetFlags(logger.Ldate | logger.Ltime | logger.LUTC | logger.Lshortfile)
	ctx = logger.WithLogger(ctx, l)

	privateKeyPath, err := exec.LookPath(args.PrivateKeyPath)
	if err != nil {
		return nil, err
	}

	toolPath, err := exec.LookPath(args.ToolPath)
	if err != nil {
		return nil, err
	}

	toolArgs := []string{
		"--key-id", args.PrivateKeyId,
		"--key-path", privateKeyPath,
	}
	if args.RequireCup {
		toolArgs = append(toolArgs, "--require-cup")
	}
	logger.Infof(ctx, "running: %s %q", toolPath, toolArgs)
	cmd := exec.CommandContext(ctx, toolPath, toolArgs...)

	if providedStderr != nil {
		cmd.Stderr = providedStderr
	} else {
		cmd.Stderr = os.Stderr
	}

	var serverStdout io.Writer
	if providedStdout == nil {
		serverStdout = os.Stdout
	} else {
		serverStdout = providedStdout
	}

	var port string

	stdoutPipe, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}

	err = cmd.Start()
	if err != nil {
		return nil, err
	}

	lineCh := make(chan string)
	go func() {
		scanner := bufio.NewScanner(stdoutPipe)
		if !scanner.Scan() {
			return
		}
		line := scanner.Text()
		lineCh <- line
		_, err := io.WriteString(serverStdout, line)
		if err != nil {
			logger.Errorf(ctx, "error: %s", err)
			return
		}

		for scanner.Scan() {
			_, err := io.WriteString(serverStdout, scanner.Text())
			if err != nil {
				logger.Errorf(ctx, "error: %s", err)
				return
			}
		}
	}()

	select {
	case line, ok := <-lineCh:
		if !ok {
			return nil, errors.New("Channel closed without receiving any lines")
		}

		// parse line
		words := strings.Fields(line)
		_, parsedPort, err := net.SplitHostPort(words[2])
		if err != nil {
			return nil, err
		}
		port = parsedPort

	case <-time.After(10 * time.Second):
		// handle timeout
		return nil, fmt.Errorf("Timed out waiting for first stdout from mock-omaha-server")
	}

	logger.Infof(ctx, "Serving Omaha from %s", port)
	hostname := strings.ReplaceAll(args.LocalHostname, "%", "%25")

	var serverURL string
	if strings.Contains(hostname, ":") {
		// This is an IPv6 address, use brackets for an IPv6 literal
		serverURL = fmt.Sprintf("http://[%s]:%s", hostname, port)
	} else {
		serverURL = fmt.Sprintf("http://%s:%s", hostname, port)
	}
	o := OmahaTool{
		Args:      args,
		port:      port,
		serverURL: serverURL,
		cmd:       cmd,
	}

	return &o, nil
}

// Returns nil if the process has already stopped.
func (o *OmahaTool) Shutdown(ctx context.Context) error {
	process := o.cmd.Process
	if process == nil {
		return nil
	}
	if err := process.Kill(); err != nil {
		return err
	}

	ch := make(chan error)
	go func() {
		ch <- o.cmd.Wait()
	}()
	select {
	case err := <-ch:
		// If the process has been killed, ignore the error and report a
		// successful shutdown.
		if _, ok := err.(*exec.ExitError); ok {
			return nil
		}
		return err
	case <-ctx.Done():
		return ctx.Err()
	}
}

func (o *OmahaTool) URL() string {
	return o.serverURL
}

func (o *OmahaTool) SetPkgURL(ctx context.Context, updatePkgURL string) error {
	// Expected input format: fuchsia-pkg://fuchsia.com/update?hash=abcdef
	u, err := url.Parse(updatePkgURL)
	if err != nil {
		return fmt.Errorf("invalid update package URL %q: %w", updatePkgURL, err)
	}
	if u.Scheme != "fuchsia-pkg" {
		return fmt.Errorf("scheme must be fuchsia-pkg, not %q", u.Scheme)
	}
	if u.Host == "" {
		return fmt.Errorf("update package URL's host must not be empty")
	}

	responsesByAppID := map[string]responseAndMetadata{
		o.Args.AppId: {
			Response:       "Update",
			Merkle:         u.Query().Get("hash"),
			CheckAssertion: "UpdatesEnabled",
			Codebase:       "fuchsia-pkg://" + u.Host + "/",
			PackagePath:    strings.TrimPrefix(u.Path, "/"),
		},
	}
	req, err := json.Marshal(responsesByAppID)
	if err != nil {
		return err
	}

	_, err = http.Post(
		fmt.Sprintf("http://localhost:%s/set_responses_by_appid", o.port),
		"application/json",
		bytes.NewBuffer(req),
	)
	return err
}
