package httpapi

import (
	"net/http"
	"os"
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"

	"productier/apps/backend/internal/authsession"
	"productier/apps/backend/internal/filestorage"
	"productier/apps/backend/internal/mailruntime"
	"productier/apps/backend/internal/store"
)

func getEnvOrDefault(key, fallback string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return fallback
}

type OAuthConfig struct {
	GoogleClientID     string
	GoogleClientSecret string
	GoogleRedirectURI  string
	SlackClientID      string
	SlackClientSecret  string
	SlackRedirectURI   string
}

type Server struct {
	engine       *gin.Engine
	mode         string
	store        store.Store
	authClient   *authsession.Client
	mail         *mailruntime.Service
	files        filestorage.Storage
	metrics      *requestMetrics
	metricsToken string
	config       OAuthConfig
}

func NewServer(
	dataStore store.Store,
	authClient *authsession.Client,
	mailService *mailruntime.Service,
	fileStorage filestorage.Storage,
	mode string,
	corsAllowOrigins []string,
	metricsToken string,
	logger *zap.Logger,
) *Server {
	engine := gin.New()
	metrics := newRequestMetrics()
	engine.Use(gin.Recovery())
	engine.Use(requestMetricsMiddleware(metrics))
	engine.Use(requestLogMiddleware(logger))
	engine.Use(requestIDMiddleware())
	engine.Use(cors.New(cors.Config{
		AllowOrigins:     corsAllowOrigins,
		AllowMethods:     []string{http.MethodGet, http.MethodPost, http.MethodPatch, http.MethodDelete, http.MethodOptions},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization", "Cookie"},
		ExposeHeaders:    []string{"Content-Length", "X-Request-Id"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	}))

	server := &Server{
		engine:       engine,
		mode:         mode,
		store:        dataStore,
		authClient:   authClient,
		mail:         mailService,
		files:        fileStorage,
		metrics:      metrics,
		metricsToken: metricsToken,
		config: OAuthConfig{
			GoogleClientID:     getEnvOrDefault("GOOGLE_CLIENT_ID", ""),
			GoogleClientSecret: getEnvOrDefault("GOOGLE_CLIENT_SECRET", ""),
			GoogleRedirectURI:  getEnvOrDefault("GOOGLE_REDIRECT_URI", "http://localhost:8080/v1/oauth/google-calendar/callback"),
			SlackClientID:      getEnvOrDefault("SLACK_CLIENT_ID", ""),
			SlackClientSecret:  getEnvOrDefault("SLACK_CLIENT_SECRET", ""),
			SlackRedirectURI:   getEnvOrDefault("SLACK_REDIRECT_URI", "http://localhost:8080/v1/oauth/slack/callback"),
		},
	}

	server.registerRoutes()
	return server
}

func (s *Server) Engine() *gin.Engine {
	return s.engine
}
