// Copyright 2023 The Shac Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package engine

import (
	"encoding/base64"
	"errors"
	"fmt"
	"net/url"
	"path"
	"regexp"
	"strings"
)

func (doc *Document) CheckVersion() error {
	if doc.MinShacVersion == "" {
		return nil
	}
	v := parseVersion(doc.MinShacVersion)
	if v == nil || len(v) > len(Version) {
		return errors.New("min_shac_version is invalid")
	}
	for i := range v {
		if v[i] > Version[i] {
			return fmt.Errorf("min_shac_version specifies unsupported version %q, running %s", doc.MinShacVersion, Version)
		}
		if v[i] < Version[i] {
			break
		}
	}
	return nil
}

// Validate verifies a shac.textproto document is valid.
func (doc *Document) Validate() error {
	if err := doc.CheckVersion(); err != nil {
		return err
	}
	deps := map[string]string{}
	aliases := map[string]struct{}{}
	if doc.Requirements != nil {
		if len(doc.Requirements.Indirect) > 0 && len(doc.Requirements.Direct) == 0 {
			return errors.New("cannot have indirect dependency without direct one")
		}
		for i, d := range doc.Requirements.Direct {
			if err := d.Validate(); err != nil {
				return fmt.Errorf("direct require block #%d: %w", i+1, err)
			}
			if _, ok := deps[d.Url]; ok {
				return fmt.Errorf("direct require block #%d: %s was already listed", i+1, d.Url)
			}
			deps[d.Url] = d.Version
			if d.Alias != "" {
				if _, ok := aliases[d.Alias]; ok {
					return fmt.Errorf("direct require block #%d: alias %s was already listed", i+1, d.Alias)
				}
				aliases[d.Alias] = struct{}{}
			}
		}
		for i, d := range doc.Requirements.Indirect {
			if err := d.Validate(); err != nil {
				return fmt.Errorf("indirect require block #%d: %w", i+1, err)
			}
			if _, ok := deps[d.Url]; ok {
				return fmt.Errorf("indirect require block #%d: %s was already listed", i+1, d.Url)
			}
			deps[d.Url] = d.Version
			if d.Alias != "" {
				if _, ok := aliases[d.Alias]; ok {
					return fmt.Errorf("indirect require block #%d: alias %s was already listed", i+1, d.Alias)
				}
				aliases[d.Alias] = struct{}{}
			}
		}
	}
	seen := map[string][]*VersionDigest{}
	if doc.Sum != nil {
		if len(deps) == 0 && len(doc.Sum.Known) > 0 {
			return errors.New("cannot have sum without at least one dependency")
		}
		for i, k := range doc.Sum.Known {
			if err := k.Validate(); err != nil {
				return fmt.Errorf("sum known block #%d: %w", i+1, err)
			}
			if _, ok := seen[k.Url]; ok {
				return fmt.Errorf("sum known block #%d: %s was already listed", i+1, k.Url)
			}
			seen[k.Url] = k.Seen
		}
	}
	// Make sure seen is a super set of deps.
	for name, version := range deps {
		known, ok := seen[name]
		if !ok {
			return fmt.Errorf("dependency %s doesn't have a known block", name)
		}
		found := false
		for _, vd := range known {
			if vd.Version == version {
				found = true
				break
			}
		}
		if !found {
			return fmt.Errorf("dependency %s doesn't have a known version %s", name, version)
		}
	}
	if doc.VendorPath != "" {
		// Make sure the path exists. We currently allow paths outside the root,
		// since it's useful for local testing. This will fail to load them
		// elsewhere.
		if path.Clean(doc.VendorPath) != doc.VendorPath {
			return fmt.Errorf("vendor_path %s is not clean", doc.VendorPath)
		}
	}
	for _, v := range doc.Vars {
		if v.Name == "" {
			return fmt.Errorf("vars cannot have empty names")
		}
	}
	return nil
}

// Validate verifies a shac.textproto require block is valid.
//
// It allows fetching from a Gerrit pending CL or a GitHub pending PR.
//
// For Gerrit, it is guaranteed to be reproducible. For GitHub, ¯\_(ツ)_/¯.
func (d *Dependency) Validate() error {
	if d.Url == "" {
		return errors.New("url must be set")
	}
	if _, err := cleanURL(d.Url); err != nil {
		return fmt.Errorf("url is invalid: %w", err)
	}
	if isBadAlias(d.Alias) {
		return errors.New("alias is invalid")
	}
	if d.Version == "" {
		return errors.New("version must be set")
	}
	// Is it a GitHub PR?
	if ok, _ := regexp.MatchString("^pull/^\\d+/head$", d.Version); !ok {
		// Is it a Gerrit CL?
		if ok, _ := regexp.MatchString("^refs/changes/\\d{1,2}/\\d{1,11}/\\d{1,3}$", d.Version); !ok {
			// Is it a hash?
			if ok, _ := regexp.MatchString("^[a-fA-F0-9]{40,64}$", d.Version); !ok {
				// Version is hopefully a git tag. This will be confirmed at checkout
				// time. Technically, git tags *are* mutable, what we do is to confirm
				// that the hash of the content is the same.
				//
				// https://git-scm.com/docs/git-check-ref-format contains the full specification.
				// Only do a minimal verification so people cannot do nasty stuff.
				if isBadVersion(d.Version) {
					return errors.New("version is invalid")
				}
			}
		}
	}
	return nil
}

// Validate verifies a shac.textproto sum known block is valid.
func (k *Known) Validate() error {
	if k.Url == "" {
		return errors.New("url must be set")
	}
	if _, err := cleanURL(k.Url); err != nil {
		return fmt.Errorf("url is invalid: %w", err)
	}
	if len(k.Seen) == 0 {
		return errors.New("there must be at least on seen entry")
	}
	l := ""
	for i, vd := range k.Seen {
		if vd.Version == "" {
			return fmt.Errorf("seen block #%d: version must be set", i+1)
		}
		if isBadVersion(vd.Version) {
			return fmt.Errorf("seen block #%d: version is invalid", i+1)
		}
		if l >= vd.Version {
			return fmt.Errorf("seen block #%d: version must be sorted", i+1)
		}
		l = vd.Version
		if vd.Digest == "" {
			return fmt.Errorf("seen block #%d: digest must be set", i+1)
		}
		if !strings.HasPrefix(vd.Digest, "h1:") {
			return fmt.Errorf("seen block #%d: digest is invalid, must start with \"h1:\"", i+1)
		}
		dec, err := base64.StdEncoding.DecodeString(vd.Digest[3:])
		if err != nil {
			return fmt.Errorf("seen block #%d: digest is invalid, %w", i+1, err)
		}
		if len(dec) != 32 {
			return fmt.Errorf("seen block #%d: digest is invalid, expected 32 bytes, got %d", i+1, len(dec))
		}
	}
	return nil
}

// Digest returns the digest for the specified url and version.
func (s *Sum) Digest(url, version string) string {
	for _, k := range s.Known {
		if k.Url == url {
			for _, vd := range k.Seen {
				if vd.Version == version {
					return vd.Digest
				}
			}
		}
	}
	// Not found.
	return ""
}

// cleanURL converts a schemaless URI to a fully qualified URI. For now
// assumes HTTPS.
func cleanURL(n string) (string, error) {
	u, err := url.Parse(n)
	if err != nil {
		return "", err
	}
	if u.Scheme != "" {
		return "", fmt.Errorf("unexpected scheme for %s", n)
	}
	if u.RawQuery != "" {
		return "", fmt.Errorf("unexpected query for %s", n)
	}
	if u.Fragment != "" {
		return "", fmt.Errorf("unexpected fragment for %s", n)
	}
	if n != u.String() {
		return "", fmt.Errorf("unclean url %s", n)
	}
	u.Scheme = "https"
	// Reparse again to ensure Host and Path are correctly set.
	if u, err = url.Parse(u.String()); err != nil {
		return "", err
	}
	if u.Host == "" {
		return "", fmt.Errorf("a hostname is required; %#v", u)
	}
	if u.Path == "" {
		return "", errors.New("a path is required")
	}
	return u.String(), nil
}

// isBadAlias return true if the alias string looks invalid.
func isBadAlias(s string) bool {
	return strings.ContainsAny(s, "$^[]{}\"'\\:+*<>=.")
}

// isBadVersion return true if the version string looks invalid.
func isBadVersion(s string) bool {
	return strings.ContainsAny(s, "$^[]{}\"'\\:+*<>=") || strings.Contains(s, "..")
}
