package server

import (
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gofiber/fiber/v2"

	"git.pbiernat.dev/egommerce/api-entities/http"
)

type (
	Server struct {
		*fiber.App
		*Config

		addr string // e.g. "127.0.0.1:8080"
		// name string // e.g. "awesome-rest-api"
		// kvNmspc   string
	}
	HeaderRequestID struct {
		RequestID string `reqHeader:"x-request-id"`
	}
	OptionFn func(*Server) error
	PurgeFn  func(*Server) error
)

func New(conf *Config) *Server {
	return &Server{
		App: fiber.New(fiber.Config{
			AppName:      conf.AppID,
			ServerHeader: conf.AppName,
			ReadTimeout:  conf.ReadTimeout * time.Millisecond,
			WriteTimeout: conf.WriteTimeout * time.Millisecond,
			IdleTimeout:  conf.IdleTimeout * time.Millisecond,
		}),
		Config: conf,
		addr:   conf.NetAddr,
	}
}

func (s *Server) Start(while chan struct{}, prgFn PurgeFn) error {
	go func() {
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
		<-sigint

		if err := prgFn(s); err != nil {
			log.Fatalf("Failed to shutdown server. Reason: %v\n", err)
		}

		close(while)
	}()

	err := s.Listen(s.addr)
	if err != nil {
		log.Fatalf("Failed to start server: %s. Reason: %v\n", s.Config.AppID, err)
		close(while)
	}
	<-while

	return err
}

func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
	var hdr = new(HeaderRequestID)
	if err := c.ReqHeaderParser(hdr); err != nil {
		return "", err
	}

	return hdr.RequestID, nil
}

func (s *Server) Error(c *fiber.Ctx, code int, msg string) error {
	return c.Status(code).JSON(http.ErrorResponse{Error: msg})
}
