package web

import (
	"context"
	"encoding/gob"
	"net/http"

	"omixlab.com/mosis-portal/internal/database"
)

func init() {
	// Register types for gob encoding (used by cookie sessions)
	gob.Register(&database.Developer{})
}

// SessionMiddleware handles session-based authentication for web pages
type SessionMiddleware struct {
	db        *database.DB
	cookieKey string
}

// NewSessionMiddleware creates a new session middleware
func NewSessionMiddleware(db *database.DB, cookieKey string) *SessionMiddleware {
	return &SessionMiddleware{
		db:        db,
		cookieKey: cookieKey,
	}
}

// LoadSession loads the developer from session cookie
func (m *SessionMiddleware) LoadSession(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Try to get developer ID from session cookie
		cookie, err := r.Cookie("session")
		if err != nil {
			next.ServeHTTP(w, r)
			return
		}

		// Lookup developer
		developer, err := m.db.GetDeveloper(r.Context(), cookie.Value)
		if err != nil {
			// Invalid session, clear cookie
			http.SetCookie(w, &http.Cookie{
				Name:     "session",
				Value:    "",
				Path:     "/",
				MaxAge:   -1,
				HttpOnly: true,
			})
			next.ServeHTTP(w, r)
			return
		}

		// Add developer to context
		ctx := context.WithValue(r.Context(), "developer", developer)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}

// RequireSession redirects to login if not authenticated
func (m *SessionMiddleware) RequireSession(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		developer := getDeveloperFromContext(r)
		if developer == nil {
			http.Redirect(w, r, "/login", http.StatusSeeOther)
			return
		}
		next.ServeHTTP(w, r)
	})
}

// SetSession creates a session for the developer
func SetSession(w http.ResponseWriter, developerID string) {
	http.SetCookie(w, &http.Cookie{
		Name:     "session",
		Value:    developerID,
		Path:     "/",
		MaxAge:   60 * 60 * 24 * 30, // 30 days
		HttpOnly: true,
		SameSite: http.SameSiteLaxMode,
	})
}

// ClearSession clears the session cookie
func ClearSession(w http.ResponseWriter) {
	http.SetCookie(w, &http.Cookie{
		Name:     "session",
		Value:    "",
		Path:     "/",
		MaxAge:   -1,
		HttpOnly: true,
	})
}
