package server

import (
	"context"
	"io/fs"
	"madsky.ru/go-finance/web"
	"os"
	"strings"

	//"github.com/doganarif/govisual"
	"github.com/gin-gonic/gin"
	"github.com/jackc/pgx/v5/pgxpool"
	"log/slog"
	"madsky.ru/go-finance/internal/repository/issue"
	"madsky.ru/go-finance/internal/repository/project"
	"madsky.ru/go-finance/internal/repository/status"
	"madsky.ru/go-finance/internal/repository/user"
	"madsky.ru/go-finance/internal/server/handlers"
	"net/http"
	"time"
)

type Server struct {
	http   *http.Server
	logger *slog.Logger
	gin    *gin.Engine
}

func NewServer(ctx context.Context, client *pgxpool.Pool, logger *slog.Logger) *Server {
	const addr = "0.0.0.0:3000"

	//r := gin.Default()
	//
	//r.GET("/ping", func(c *gin.Context) {
	//	c.JSON(http.StatusOK, gin.H{
	//		"message": "pong",
	//	})
	//})

	mux := http.NewServeMux()

	mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		dist, err := fs.Sub(web.DistDir, "dist")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}

		f, err := dist.Open(strings.TrimPrefix(r.URL.Path, "/"))
		if err == nil {
			defer func(f fs.File) {
				err := f.Close()
				if err != nil {
					logger.Error("error close file", err)
				}
			}(f)
		}

		if os.IsNotExist(err) {
			r.URL.Path = "/"
		}

		http.FileServer(http.FS(dist)).ServeHTTP(w, r)
	}))

	//http://localhost:8080/__viz
	//handler := govisual.Wrap(
	//	mux,
	//	govisual.WithRequestBodyLogging(true),
	//	govisual.WithResponseBodyLogging(true),
	//)
	//handler := middleware.LoggingMiddleware(mux, logger)

	projectsRepository := project.NewRepository(client)
	handlers.RegisterProjectRoutes(mux, ctx, projectsRepository)

	statusRepository := status.NewRepository(client)
	handlers.RegisterStatusRoutes(mux, ctx, statusRepository)

	issueRepository := issue.NewRepository(client)
	handlers.RegisterIssueRoutes(mux, ctx, issueRepository)

	userRepository := user.NewRepository(client)
	handlers.RegisterAuthRoutes(mux, ctx, userRepository)

	//mux.Handle("/api/", http.StripPrefix("/api", apiHandler))
	//logger.Info("start server", slog.String("addr", addr))

	return &Server{
		logger: logger,
		//gin:    r,
		http: &http.Server{
			Addr:           addr,
			Handler:        mux,
			ReadTimeout:    10 * time.Second,
			WriteTimeout:   10 * time.Second,
			MaxHeaderBytes: 1 << 20,
		},
	}
}

func (s *Server) Start() error {
	//s.gin.Run('0.0.0.0:3000')
	return s.http.ListenAndServe()
}

func (s *Server) Stop() error {
	s.logger.Info("stopping http server")

	return s.http.Close()
}
