package diagnostic

import (
	"context"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"strconv"
	"sync"
	"sync/atomic"
	"time"

	"github.com/containerd/log"
	"github.com/docker/docker/libnetwork/internal/caller"
	"github.com/docker/docker/pkg/stack"
)

// Server when the debug is enabled exposes a
// This data structure is protected by the Agent mutex so does not require and additional mutex here
type Server struct {
	mu       sync.Mutex
	enable   int32
	srv      *http.Server
	port     int
	mux      *http.ServeMux
	handlers map[string]http.Handler
}

// New creates a new diagnostic server
func New() *Server {
	s := &Server{
		mux:      http.NewServeMux(),
		handlers: make(map[string]http.Handler),
	}
	s.HandleFunc("/", notImplemented)
	s.HandleFunc("/help", s.help)
	s.HandleFunc("/ready", ready)
	s.HandleFunc("/stackdump", stackTrace)
	return s
}

// Handle registers the handler for the given pattern,
// replacing any existing handler.
func (s *Server) Handle(pattern string, handler http.Handler) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if _, ok := s.handlers[pattern]; !ok {
		// Register a handler on the mux which allows the underlying handler to
		// be dynamically switched out. The http.ServeMux will panic if one
		// attempts to register a handler for the same pattern twice.
		s.mux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
			s.mu.Lock()
			h := s.handlers[pattern]
			s.mu.Unlock()
			h.ServeHTTP(w, r)
		})
	}
	s.handlers[pattern] = handler
}

// Handle registers the handler function for the given pattern,
// replacing any existing handler.
func (s *Server) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
	s.Handle(pattern, http.HandlerFunc(handler))
}

// ServeHTTP this is the method called bu the ListenAndServe, and is needed to allow us to
// use our custom mux
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	s.mux.ServeHTTP(w, r)
}

// EnableDiagnostic opens a TCP socket to debug the passed network DB
func (s *Server) EnableDiagnostic(ip string, port int) {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.port = port

	if s.enable == 1 {
		log.G(context.TODO()).Info("The server is already up and running")
		return
	}

	log.G(context.TODO()).Infof("Starting the diagnostic server listening on %d for commands", port)
	srv := &http.Server{
		Addr:              net.JoinHostPort(ip, strconv.Itoa(port)),
		Handler:           s,
		ReadHeaderTimeout: 5 * time.Minute, // "G112: Potential Slowloris Attack (gosec)"; not a real concern for our use, so setting a long timeout.
	}
	s.srv = srv
	s.enable = 1
	go func(n *Server) {
		// Ignore ErrServerClosed that is returned on the Shutdown call
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.G(context.TODO()).Errorf("ListenAndServe error: %s", err)
			atomic.SwapInt32(&n.enable, 0)
		}
	}(s)
}

// DisableDiagnostic stop the debug and closes the tcp socket
func (s *Server) DisableDiagnostic() {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.srv.Shutdown(context.Background()) //nolint:errcheck
	s.srv = nil
	s.enable = 0
	log.G(context.TODO()).Info("Disabling the diagnostic server")
}

// IsDiagnosticEnabled returns true when the debug is enabled
func (s *Server) IsDiagnosticEnabled() bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	return s.enable == 1
}

func notImplemented(w http.ResponseWriter, r *http.Request) {
	_ = r.ParseForm()
	_, jsonOutput := ParseHTTPFormOptions(r)
	rsp := WrongCommand("not implemented", fmt.Sprintf("URL path: %s no method implemented check /help\n", r.URL.Path))

	// audit logs
	log.G(context.TODO()).WithFields(log.Fields{
		"component": "diagnostic",
		"remoteIP":  r.RemoteAddr,
		"method":    caller.Name(0),
		"url":       r.URL.String(),
	}).Info("command not implemented done")

	_, _ = HTTPReply(w, rsp, jsonOutput)
}

func (s *Server) help(w http.ResponseWriter, r *http.Request) {
	_ = r.ParseForm()
	_, jsonOutput := ParseHTTPFormOptions(r)

	// audit logs
	log.G(context.TODO()).WithFields(log.Fields{
		"component": "diagnostic",
		"remoteIP":  r.RemoteAddr,
		"method":    caller.Name(0),
		"url":       r.URL.String(),
	}).Info("help done")

	var result string
	s.mu.Lock()
	for path := range s.handlers {
		result += fmt.Sprintf("%s\n", path)
	}
	s.mu.Unlock()
	_, _ = HTTPReply(w, CommandSucceed(&StringCmd{Info: result}), jsonOutput)
}

func ready(w http.ResponseWriter, r *http.Request) {
	_ = r.ParseForm()
	_, jsonOutput := ParseHTTPFormOptions(r)

	// audit logs
	log.G(context.TODO()).WithFields(log.Fields{
		"component": "diagnostic",
		"remoteIP":  r.RemoteAddr,
		"method":    caller.Name(0),
		"url":       r.URL.String(),
	}).Info("ready done")
	_, _ = HTTPReply(w, CommandSucceed(&StringCmd{Info: "OK"}), jsonOutput)
}

func stackTrace(w http.ResponseWriter, r *http.Request) {
	_ = r.ParseForm()
	_, jsonOutput := ParseHTTPFormOptions(r)

	// audit logs
	logger := log.G(context.TODO()).WithFields(log.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
	logger.Info("stack trace")

	path, err := stack.DumpToFile("/tmp/")
	if err != nil {
		logger.WithError(err).Error("failed to write goroutines dump")
		_, _ = HTTPReply(w, FailCommand(err), jsonOutput)
	} else {
		logger.Info("stack trace done")
		_, _ = HTTPReply(w, CommandSucceed(&StringCmd{Info: "goroutine stacks written to " + path}), jsonOutput)
	}
}

// DebugHTTPForm helper to print the form url parameters
func DebugHTTPForm(r *http.Request) {
	for k, v := range r.Form {
		log.G(context.TODO()).Debugf("Form[%q] = %q\n", k, v)
	}
}

// JSONOutput contains details on JSON output printing
type JSONOutput struct {
	enable      bool
	prettyPrint bool
}

// ParseHTTPFormOptions easily parse the JSON printing options
func ParseHTTPFormOptions(r *http.Request) (bool, *JSONOutput) {
	_, unsafe := r.Form["unsafe"]
	v, enableJSON := r.Form["json"]
	var pretty bool
	if len(v) > 0 {
		pretty = v[0] == "pretty"
	}
	return unsafe, &JSONOutput{enable: enableJSON, prettyPrint: pretty}
}

// HTTPReply helper function that takes care of sending the message out
func HTTPReply(w http.ResponseWriter, r *HTTPResult, j *JSONOutput) (int, error) {
	var response []byte
	if j.enable {
		w.Header().Set("Content-Type", "application/json")
		var err error
		if j.prettyPrint {
			response, err = json.MarshalIndent(r, "", "  ")
			if err != nil {
				response, _ = json.MarshalIndent(FailCommand(err), "", "  ")
			}
		} else {
			response, err = json.Marshal(r)
			if err != nil {
				response, _ = json.Marshal(FailCommand(err))
			}
		}
	} else {
		response = []byte(r.String())
	}
	return fmt.Fprint(w, string(response))
}
