// Copyright 2019 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 sumdb implements the HTTP protocols for serving or accessing a module checksum database.
package sumdb

import (
	"context"
	"net/http"
	"os"
	"strings"

	"golang.org/x/mod/internal/lazyregexp"
	"golang.org/x/mod/module"
	"golang.org/x/mod/sumdb/tlog"
)

// A ServerOps provides the external operations
// (underlying database access and so on) needed by the [Server].
type ServerOps interface {
	// Signed returns the signed hash of the latest tree.
	Signed(ctx context.Context) ([]byte, error)

	// ReadRecords returns the content for the n records id through id+n-1.
	ReadRecords(ctx context.Context, id, n int64) ([][]byte, error)

	// Lookup looks up a record for the given module,
	// returning the record ID.
	Lookup(ctx context.Context, m module.Version) (int64, error)

	// ReadTileData reads the content of tile t.
	// It is only invoked for hash tiles (t.L ≥ 0).
	ReadTileData(ctx context.Context, t tlog.Tile) ([]byte, error)
}

// A Server is the checksum database HTTP server,
// which implements http.Handler and should be invoked
// to serve the paths listed in [ServerPaths].
type Server struct {
	ops ServerOps
}

// NewServer returns a new Server using the given operations.
func NewServer(ops ServerOps) *Server {
	return &Server{ops: ops}
}

// ServerPaths are the URL paths the Server can (and should) serve.
//
// Typically a server will do:
//
//	srv := sumdb.NewServer(ops)
//	for _, path := range sumdb.ServerPaths {
//		http.Handle(path, srv)
//	}
var ServerPaths = []string{
	"/lookup/",
	"/latest",
	"/tile/",
}

var modVerRE = lazyregexp.New(`^[^@]+@v[0-9]+\.[0-9]+\.[0-9]+(-[^@]*)?(\+incompatible)?$`)

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	switch {
	default:
		http.NotFound(w, r)

	case strings.HasPrefix(r.URL.Path, "/lookup/"):
		mod := strings.TrimPrefix(r.URL.Path, "/lookup/")
		if !modVerRE.MatchString(mod) {
			http.Error(w, "invalid module@version syntax", http.StatusBadRequest)
			return
		}
		i := strings.Index(mod, "@")
		escPath, escVers := mod[:i], mod[i+1:]
		path, err := module.UnescapePath(escPath)
		if err != nil {
			reportError(w, err)
			return
		}
		vers, err := module.UnescapeVersion(escVers)
		if err != nil {
			reportError(w, err)
			return
		}
		id, err := s.ops.Lookup(ctx, module.Version{Path: path, Version: vers})
		if err != nil {
			reportError(w, err)
			return
		}
		records, err := s.ops.ReadRecords(ctx, id, 1)
		if err != nil {
			// This should never happen - the lookup says the record exists.
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if len(records) != 1 {
			http.Error(w, "invalid record count returned by ReadRecords", http.StatusInternalServerError)
			return
		}
		msg, err := tlog.FormatRecord(id, records[0])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		signed, err := s.ops.Signed(ctx)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
		w.Write(msg)
		w.Write(signed)

	case r.URL.Path == "/latest":
		data, err := s.ops.Signed(ctx)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
		w.Write(data)

	case strings.HasPrefix(r.URL.Path, "/tile/"):
		t, err := tlog.ParseTilePath(r.URL.Path[1:])
		if err != nil {
			http.Error(w, "invalid tile syntax", http.StatusBadRequest)
			return
		}
		if t.L == -1 {
			// Record data.
			start := t.N << uint(t.H)
			records, err := s.ops.ReadRecords(ctx, start, int64(t.W))
			if err != nil {
				reportError(w, err)
				return
			}
			if len(records) != t.W {
				http.Error(w, "invalid record count returned by ReadRecords", http.StatusInternalServerError)
				return
			}
			var data []byte
			for i, text := range records {
				msg, err := tlog.FormatRecord(start+int64(i), text)
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
				data = append(data, msg...)
			}
			w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
			w.Write(data)
			return
		}

		data, err := s.ops.ReadTileData(ctx, t)
		if err != nil {
			reportError(w, err)
			return
		}
		w.Header().Set("Content-Type", "application/octet-stream")
		w.Write(data)
	}
}

// reportError reports err to w.
// If it's a not-found, the reported error is 404.
// Otherwise it is an internal server error.
// The caller must only call reportError in contexts where
// a not-found err should be reported as 404.
func reportError(w http.ResponseWriter, err error) {
	if os.IsNotExist(err) {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	http.Error(w, err.Error(), http.StatusInternalServerError)
}
