package server

import (
	"context"
	"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/server/handlers"
	"madsky.ru/go-finance/internal/server/middleware"
	"madsky.ru/go-finance/web"
	"net/http"
	"time"
)

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

func RegisterProjectRoutes(mux *http.ServeMux, ctx context.Context, repository project.Repository) {
	mux.HandleFunc("GET /api/projects", handlers.FindProjects(ctx, repository))
	mux.HandleFunc("GET /api/projects/{id}", handlers.FindProjectByID(ctx, repository))
	mux.HandleFunc("POST /api/projects", handlers.CreateProject(ctx, repository))
	mux.HandleFunc("PUT /api/projects/{id}", handlers.UpdateProject(ctx, repository))
	mux.HandleFunc("DELETE /api/projects/{id}", handlers.DeleteProject(ctx, repository))
}

func RegisterStatusRoutes(mux *http.ServeMux, ctx context.Context, repository status.Repository) {
	mux.HandleFunc("GET /api/statuses/", handlers.FindStatuses(ctx, repository))
	mux.HandleFunc("GET /api/statuses/{id}", handlers.FindStatusById(ctx, repository))
	mux.HandleFunc("POST /api/statuses", handlers.CreateStatus(ctx, repository))
	mux.HandleFunc("DELETE /api/statuses/{id}", handlers.DeleteStatus(ctx, repository))
}

func RegisterIssueRoutes(mux *http.ServeMux, ctx context.Context, repository issue.Repository) {
	mux.HandleFunc("GET /api/issues/", handlers.FindIssues(ctx, repository))
	mux.HandleFunc("GET /api/issues/{id}", handlers.FindIssuesByID(ctx, repository))
	mux.HandleFunc("POST /api/issues", handlers.CreateIssues(ctx, repository))
	mux.HandleFunc("POST /api/issues/positions", handlers.UpdatePositions(ctx, repository))
	mux.HandleFunc("DELETE /api/issues/{id}", handlers.DeleteIssues(ctx, repository))
}

func NewServer(ctx context.Context, client *pgxpool.Pool, logger *slog.Logger) *Server {
	const addr = "localhost:3000"
	mux := http.NewServeMux()
	mux.Handle("/", http.FileServer(http.FS(web.Dist)))

	handler := middleware.LoggingMiddleware(mux, logger)

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

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

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

	logger.Info("start server", slog.String("addr", addr))

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

func (s *Server) Start() error {
	return s.http.ListenAndServe()
}

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

	return s.http.Close()
}
