// Copyright 2021 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 worker

import (
	"bytes"
	"context"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/google/safehtml/template"
	"golang.org/x/exp/event"
	"golang.org/x/sync/errgroup"
	"golang.org/x/vuln/internal/derrors"
	"golang.org/x/vuln/internal/gitrepo"
	"golang.org/x/vuln/internal/worker/log"
	"golang.org/x/vuln/internal/worker/store"
)

var staticPath = template.TrustedSourceFromConstant("internal/worker/static")

type Server struct {
	namespace string
	st        store.Store

	indexTemplate *template.Template
}

func NewServer(ctx context.Context, namespace string, st store.Store) (_ *Server, err error) {
	defer derrors.Wrap(&err, "NewServer(%q)", namespace)

	s := &Server{namespace: namespace, st: st}
	s.indexTemplate, err = parseTemplate(staticPath, template.TrustedSourceFromConstant("index.tmpl"))
	if err != nil {
		return nil, err
	}
	s.handle(ctx, "/", s.indexPage)
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(staticPath.String()))))
	s.handle(ctx, "/favicon.ico", func(w http.ResponseWriter, r *http.Request) error {
		http.ServeFile(w, r, filepath.Join(staticPath.String(), "favicon.ico"))
		return nil
	})
	return s, nil
}

func (s *Server) handle(ctx context.Context, pattern string, handler func(w http.ResponseWriter, r *http.Request) error) {
	http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		traceID := r.Header.Get("X-Cloud-Trace-Context")

		log.Info(ctx, "request start",
			event.Value("httpRequest", r),
			event.String("traceID", traceID))

		r = r.WithContext(log.WithLineLogger(r.Context()))
		w2 := &responseWriter{ResponseWriter: w}
		if err := handler(w2, r); err != nil {
			s.serveError(ctx, w2, r, err)
		}

		log.Info(ctx, "request end",
			event.Value("traceID", traceID),
			event.Duration("latency", time.Since(start)),
			event.Int64("status", translateStatus(w2.status)))
	})
}

func (s *Server) serveError(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) {
	errString := err.Error()
	log.Error(ctx, errString)
	http.Error(w, errString, http.StatusInternalServerError)
}

type responseWriter struct {
	http.ResponseWriter
	status int
}

func (rw *responseWriter) WriteHeader(code int) {
	rw.status = code
	rw.ResponseWriter.WriteHeader(code)
}

func translateStatus(code int) int64 {
	if code == 0 {
		return http.StatusOK
	}
	return int64(code)
}

// Parse a template.
func parseTemplate(staticPath, filename template.TrustedSource) (*template.Template, error) {
	if staticPath.String() == "" {
		return nil, nil
	}
	templatePath := template.TrustedSourceJoin(staticPath, filename)
	return template.New(filename.String()).Funcs(template.FuncMap{
		"timefmt": formatTime,
	}).ParseFilesFromTrustedSources(templatePath)
}

var locNewYork *time.Location

func init() {
	var err error
	locNewYork, err = time.LoadLocation("America/New_York")
	if err != nil {
		log.Errorf(context.Background(), "time.LoadLocation: %v", err)
		os.Exit(1)
	}
}

func formatTime(t *time.Time) string {
	if t == nil || t.IsZero() {
		return "-"
	}
	return t.In(locNewYork).Format("2006-01-02 15:04:05")
}

func renderPage(ctx context.Context, w http.ResponseWriter, page interface{}, tmpl *template.Template) (err error) {
	defer derrors.Wrap(&err, "renderPage")

	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, page); err != nil {
		return err
	}
	if _, err := io.Copy(w, &buf); err != nil {
		log.Error(ctx, "copying buffer to ResponseWriter", event.Value("error", err))
		return err
	}
	return nil
}

type indexPage struct {
	CVEListRepoURL   string
	Namespace        string
	Updates          []*store.CommitUpdateRecord
	CVEsNeedingIssue []*store.CVERecord
	CVEsUpdatedSince []*store.CVERecord
}

func (s *Server) indexPage(w http.ResponseWriter, r *http.Request) error {

	var (
		updates                    []*store.CommitUpdateRecord
		needingIssue, updatedSince []*store.CVERecord
	)

	g, ctx := errgroup.WithContext(r.Context())
	g.Go(func() error {
		var err error
		updates, err = s.st.ListCommitUpdateRecords(ctx, 10)
		return err
	})
	g.Go(func() error {
		var err error
		needingIssue, err = s.st.ListCVERecordsWithTriageState(ctx, store.TriageStateNeedsIssue)
		return err
	})
	g.Go(func() error {
		var err error
		updatedSince, err = s.st.ListCVERecordsWithTriageState(ctx, store.TriageStateUpdatedSinceIssueCreation)
		return err
	})
	if err := g.Wait(); err != nil {
		return err
	}

	page := indexPage{
		CVEListRepoURL:   gitrepo.CVEListRepoURL,
		Namespace:        s.namespace,
		Updates:          updates,
		CVEsNeedingIssue: needingIssue,
		CVEsUpdatedSince: updatedSince,
	}
	return renderPage(r.Context(), w, page, s.indexTemplate)
}
