// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

package webug

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/google/uuid"
	"k8s.io/klog/v2"

	"source.monogon.dev/cloud/bmaas/bmdb/model"
	"source.monogon.dev/cloud/bmaas/bmdb/reflection"
)

// baseParams are passed to all rendered templates, and are consumed by tags in
// templates/base.gohtml.
type baseParams struct {
	// Address to display in page header.
	BMDBAddress string
	// Schema version to display in page header.
	BMDBSchema string
}

// makeBase builds baseParams from information about the current connection.
func (s *server) makeBase() baseParams {
	address := fmt.Sprintf("%s@%s", s.conn.DatabaseName, s.conn.Address)
	if s.conn.InMemory {
		address += " (in memory)"
	}
	return baseParams{
		BMDBAddress: address,
		BMDBSchema:  s.curSchema().Version,
	}
}

// viewMachines renders a list of all machines in the BMDB.
func (s *server) viewMachines(w http.ResponseWriter, r *http.Request, args ...string) {
	start := time.Now()
	res, err := s.curSchema().GetMachines(r.Context(), &reflection.GetMachinesOpts{Strict: s.strictConsistency})
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "could not dump BMDB: %v", err)
		return
	}
	duration := time.Since(start)

	tagCount := make(map[string]int)
	for _, d := range res.Data {
		for _, t := range d.Tags {
			tagCount[t.Type.Name()]++
		}
	}

	type params struct {
		Base       baseParams
		Query      string
		Machines   []*reflection.Machine
		NMachines  int
		RenderTime time.Duration
		TagCount   map[string]int
	}
	err = templates.ExecuteTemplate(w, "machines.gohtml", &params{
		Base:       s.makeBase(),
		Query:      res.Query,
		Machines:   res.Data,
		NMachines:  len(res.Data),
		RenderTime: duration,
		TagCount:   tagCount,
	})
	if err != nil {
		klog.Errorf("Template rendering failed: %v", err)
	}
}

// viewMachineDetail renders a detailed page for a single machine.
func (s *server) viewMachineDetail(w http.ResponseWriter, r *http.Request, args ...string) {
	mid, err := uuid.Parse(args[0])
	if err != nil {
		w.WriteHeader(http.StatusUnprocessableEntity)
		fmt.Fprintf(w, "invalid machine UUID")
		return
	}

	opts := reflection.GetMachinesOpts{
		FilterMachine:   &mid,
		Strict:          s.strictConsistency,
		ExpiredBackoffs: true,
	}
	res, err := s.curSchema().GetMachines(r.Context(), &opts)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "could not dump BMDB: %v", err)
		return
	}
	if len(res.Data) == 0 {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprintf(w, "machine not found")
		return
	}
	machine := res.Data[0]

	// Params to pass to template.
	type sessionOrError struct {
		Session *model.Session
		Error   string
	}
	type params struct {
		Base    baseParams
		Machine *reflection.Machine

		HistoryError string
		History      []model.WorkHistory

		Sessions map[string]sessionOrError
	}
	p := params{
		Base:     s.makeBase(),
		Machine:  machine,
		Sessions: make(map[string]sessionOrError),
	}

	// History retrieval is performed with strict consistency guarantees, and thus
	// might block. Make sure we don't block the entire page.
	subQueriesCtx, subQueriesCtxC := context.WithTimeout(r.Context(), time.Second)
	defer subQueriesCtxC()
	history, err := s.conn.ListHistoryOf(subQueriesCtx, mid)
	if err != nil {
		p.HistoryError = err.Error()
	}

	// Same for sessions.
	for name, work := range machine.Work {
		sessions, err := s.conn.GetSession(subQueriesCtx, work.SessionID)
		if err != nil {
			p.Sessions[name] = sessionOrError{Error: err.Error()}
		} else {
			if len(sessions) == 0 {
				// This can happen if the session literally just disappeared.
				//
				// TODO(q3k): put all of these operations in a DB TX so that we don't end up with
				// possible inconsistencies?
				p.Sessions[name] = sessionOrError{Error: "not found"}
				continue
			}
			p.Sessions[name] = sessionOrError{Session: &sessions[0]}
		}
	}

	p.History = make([]model.WorkHistory, len(history))
	for i := 0; i < len(history); i += 1 {
		p.History[i] = history[len(history)-(i+1)]
	}
	if err := templates.ExecuteTemplate(w, "machine.gohtml", &p); err != nil {
		klog.Errorf("Template rendering failed: %v", err)
	}
}

// viewProviderRedirects redirects a given provider and provider_id into a
// provider's web portal for more detailed information about an underlying
// machine.
func (s *server) viewProviderRedirect(w http.ResponseWriter, r *http.Request, args ...string) {
	providerUrls := map[string]string{
		"Equinix": "https://console.equinix.com/devices/%s/overview",
	}
	if providerUrls[args[0]] == "" {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprintf(w, "Usage: /provider/Equinix/<id>")
		return
	}
	url := fmt.Sprintf(providerUrls[args[0]], args[1])
	http.Redirect(w, r, url, http.StatusFound)
}

// viewSession shows detailed information about a BMDB session.
func (s *server) viewSession(w http.ResponseWriter, r *http.Request, args ...string) {
	// TODO(q3k): implement this once we add session info to work history so that
	// this can actually display something useful.
	fmt.Fprintf(w, "underconstruction.gif")
}
