// Copyright 2015 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 gerrit

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	"golang.org/x/oauth2"
)

// Auth is a Gerrit authentication mode.
// The most common ones are NoAuth or BasicAuth.
type Auth interface {
	setAuth(*Client, *http.Request) error
}

// BasicAuth sends a username and password.
func BasicAuth(username, password string) Auth {
	return basicAuth{username, password}
}

type basicAuth struct {
	username, password string
}

func (ba basicAuth) setAuth(c *Client, r *http.Request) error {
	r.SetBasicAuth(ba.username, ba.password)
	return nil
}

// GitCookiesAuth derives the Gerrit authentication token from
// gitcookies based on the URL of the Gerrit request.
// The cookie file used is determined by running "git config
// http.cookiefile" in the current directory.
// To use a specific file, see GitCookieFileAuth.
func GitCookiesAuth() Auth {
	return gitCookiesAuth{}
}

// GitCookieFileAuth derives the Gerrit authentication token from the
// provided gitcookies file. It is equivalent to GitCookiesAuth,
// except that "git config http.cookiefile" is not used to find which
// cookie file to use.
func GitCookieFileAuth(file string) Auth {
	return &gitCookieFileAuth{file: file}
}

func netrcPath() string {
	if runtime.GOOS == "windows" {
		return filepath.Join(os.Getenv("USERPROFILE"), "_netrc")
	}
	return filepath.Join(os.Getenv("HOME"), ".netrc")
}

type gitCookiesAuth struct{}

func (gitCookiesAuth) setAuth(c *Client, r *http.Request) error {
	// First look in Git's http.cookiefile, which is where Gerrit
	// now tells users to store this information.
	git := exec.Command("git", "config", "http.cookiefile")
	git.Stderr = os.Stderr

	// Ignore a failure here, git will exit(1) if no cookies are
	// present and prevent the netrc from being read below.
	gitOut, _ := git.Output()

	cookieFile := strings.TrimSpace(string(gitOut))
	if len(cookieFile) != 0 {
		auth := &gitCookieFileAuth{file: cookieFile}
		if err := auth.setAuth(c, r); err != nil {
			return err
		}
		if len(r.Header["Cookie"]) > 0 {
			return nil
		}
	}

	url, err := url.Parse(c.url)
	if err != nil {
		return err
	}

	// If not there, then look in $HOME/.netrc, which is where Gerrit
	// used to tell users to store the information, until the passwords
	// got so long that old versions of curl couldn't handle them.
	host := url.Host
	netrc := netrcPath()
	data, _ := os.ReadFile(netrc)
	for _, line := range strings.Split(string(data), "\n") {
		if i := strings.Index(line, "#"); i >= 0 {
			line = line[:i]
		}
		f := strings.Fields(line)
		if len(f) >= 6 && f[0] == "machine" && f[1] == host && f[2] == "login" && f[4] == "password" {
			r.SetBasicAuth(f[3], f[5])
			return nil
		}
	}
	return fmt.Errorf("no authentication configured for Gerrit; tried both git config http.cookiefile and %s", netrc)
}

type gitCookieFileAuth struct {
	file string

	once sync.Once
	jar  *cookiejar.Jar
	err  error
}

func (a *gitCookieFileAuth) loadCookieFileOnce() {
	data, err := os.ReadFile(a.file)
	if err != nil {
		a.err = fmt.Errorf("Error loading cookie file: %v", err)
		return
	}
	a.jar = parseGitCookies(string(data))
}

func (a *gitCookieFileAuth) setAuth(c *Client, r *http.Request) error {
	a.once.Do(a.loadCookieFileOnce)
	if a.err != nil {
		return a.err
	}

	url, err := url.Parse(c.url)
	if err != nil {
		return err
	}

	for _, cookie := range a.jar.Cookies(url) {
		r.AddCookie(cookie)
	}
	return nil
}

func parseGitCookies(data string) *cookiejar.Jar {
	jar, _ := cookiejar.New(nil)
	for _, line := range strings.Split(data, "\n") {
		f := strings.Split(line, "\t")
		if len(f) < 7 {
			continue
		}
		expires, err := strconv.ParseInt(f[4], 10, 64)
		if err != nil {
			continue
		}
		c := http.Cookie{
			Domain:  f[0],
			Path:    f[2],
			Secure:  f[3] == "TRUE",
			Expires: time.Unix(expires, 0),
			Name:    f[5],
			Value:   f[6],
		}
		// Construct a fake URL to add c to the jar.
		url := url.URL{
			Scheme: "http",
			Host:   c.Domain,
			Path:   c.Path,
		}
		jar.SetCookies(&url, []*http.Cookie{&c})
	}
	return jar
}

// Scopes to use when creating a TokenSource.
var OAuth2Scopes = []string{
	"https://www.googleapis.com/auth/cloud-platform",
	"https://www.googleapis.com/auth/gerritcodereview",
	"https://www.googleapis.com/auth/source.full_control",
	"https://www.googleapis.com/auth/source.read_write",
	"https://www.googleapis.com/auth/source.read_only",
}

// OAuth2Auth uses the given TokenSource to authenticate requests.
func OAuth2Auth(src oauth2.TokenSource) Auth {
	return oauth2Auth{src}
}

type oauth2Auth struct {
	src oauth2.TokenSource
}

func (a oauth2Auth) setAuth(c *Client, r *http.Request) error {
	token, err := a.src.Token()
	if err != nil {
		return err
	}
	token.SetAuthHeader(r)
	return nil
}

// NoAuth makes requests unauthenticated.
var NoAuth = noAuth{}

type noAuth struct{}

func (noAuth) setAuth(c *Client, r *http.Request) error {
	return nil
}

type digestAuth struct {
	Username, Password, Realm, NONCE, QOP, Opaque, Algorithm string
}

func getDigestAuth(username, password string, resp *http.Response) *digestAuth {
	header := resp.Header.Get("www-authenticate")
	parts := strings.SplitN(header, " ", 2)
	parts = strings.Split(parts[1], ", ")
	opts := make(map[string]string)

	for _, part := range parts {
		vals := strings.SplitN(part, "=", 2)
		key := vals[0]
		val := strings.Trim(vals[1], "\",")
		opts[key] = val
	}

	auth := digestAuth{
		username, password,
		opts["realm"], opts["nonce"], opts["qop"], opts["opaque"], opts["algorithm"],
	}
	return &auth
}

func setDigestAuth(r *http.Request, username, password string, resp *http.Response, nc int) {
	auth := getDigestAuth(username, password, resp)
	authStr := getDigestAuthString(auth, r.URL, r.Method, nc)
	r.Header.Add("Authorization", authStr)
}

func getDigestAuthString(auth *digestAuth, url *url.URL, method string, nc int) string {
	var buf bytes.Buffer
	h := md5.New()
	fmt.Fprintf(&buf, "%s:%s:%s", auth.Username, auth.Realm, auth.Password)
	buf.WriteTo(h)
	ha1 := hex.EncodeToString(h.Sum(nil))

	h = md5.New()
	fmt.Fprintf(&buf, "%s:%s", method, url.Path)
	buf.WriteTo(h)
	ha2 := hex.EncodeToString(h.Sum(nil))

	ncStr := fmt.Sprintf("%08x", nc)
	hnc := "MTM3MDgw"

	h = md5.New()
	fmt.Fprintf(&buf, "%s:%s:%s:%s:%s:%s", ha1, auth.NONCE, ncStr, hnc, auth.QOP, ha2)
	buf.WriteTo(h)
	respdig := hex.EncodeToString(h.Sum(nil))

	buf.Write([]byte("Digest "))
	fmt.Fprintf(&buf,
		`username="%s", realm="%s", nonce="%s", uri="%s", response="%s"`,
		auth.Username, auth.Realm, auth.NONCE, url.Path, respdig,
	)

	if auth.Opaque != "" {
		fmt.Fprintf(&buf, `, opaque="%s"`, auth.Opaque)
	}
	if auth.QOP != "" {
		fmt.Fprintf(&buf, `, qop="%s", nc=%s, cnonce="%s"`, auth.QOP, ncStr, hnc)
	}
	if auth.Algorithm != "" {
		fmt.Fprintf(&buf, `, algorithm="%s"`, auth.Algorithm)
	}

	return buf.String()
}

func (a digestAuth) setAuth(c *Client, r *http.Request) error {
	resp, err := http.Get(r.URL.String())
	if err != nil {
		return err
	}
	setDigestAuth(r, a.Username, a.Password, resp, 1)
	return nil
}

// DigestAuth returns an Auth implementation which sends
// the provided username and password using HTTP Digest Authentication
// (RFC 2617)
func DigestAuth(username, password string) Auth {
	return digestAuth{
		Username: username,
		Password: password,
	}
}
