package middleware

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

	"github.com/boj/redistore"
	"github.com/google/uuid"
	"github.com/gorilla/sessions"
	"github.com/labstack/echo-contrib/session"
	"github.com/labstack/echo/v4"

	"github.com/chaitin/panda-wiki/config"
	"github.com/chaitin/panda-wiki/log"
	"github.com/chaitin/panda-wiki/store/cache"
)

const (
	SessionKey = "SessionKey"
)

type SessionMiddleware struct {
	logger *log.Logger
	store  *redistore.RediStore
}

func NewSessionMiddleware(logger *log.Logger, config *config.Config, cache *cache.Cache) (*SessionMiddleware, error) {

	secretKey, err := cache.GetOrSet(context.Background(), SessionKey, uuid.New().String(), time.Duration(0))
	if err != nil {
		logger.Error("session store create secret key failed: %v", log.Error(err))
		return nil, err
	}

	store, err := redistore.NewRediStore(
		10,
		"tcp",
		config.Redis.Addr,
		"",
		config.Redis.Password,
		[]byte(secretKey.(string)),
	)

	if err != nil {
		logger.Error("init session store failed: %v", log.Error(err))
		return nil, err
	}

	store.Options = &sessions.Options{
		Path:     "/",
		MaxAge:   30 * 86400,
		SameSite: http.SameSiteLaxMode,
		HttpOnly: true,
	}

	return &SessionMiddleware{
		logger: logger.WithModule("middleware.session"),
		store:  store,
	}, nil
}

func (s *SessionMiddleware) Session() echo.MiddlewareFunc {
	return session.MiddlewareWithConfig(session.Config{
		Store: s.store,
	})
}
