package app

import (
	"fmt"
	"time"

	"git.linuxforward.com/byop/byop-engine/auth"
	"git.linuxforward.com/byop/byop-engine/cloud"
	"git.linuxforward.com/byop/byop-engine/dbmanager"
	"git.linuxforward.com/byop/byop-engine/dbstore"
	"git.linuxforward.com/byop/byop-engine/handlers"
	mw "git.linuxforward.com/byop/byop-engine/middleware"
	"git.linuxforward.com/byop/byop-engine/services"
	"github.com/pkg/errors"

	"github.com/gin-gonic/gin"
)

func (a *App) initCommonServices() error {
	// Initialize token store
	a.tokenStore = auth.NewMemoryTokenStore(time.Duration(a.cnf.Auth.CleanupInterval))

	// Initialize authentication service
	a.authService = auth.NewJWTService(
		[]byte(a.cnf.Auth.PrivateKey),
		time.Duration(a.cnf.Auth.TokenDuration),
		a.tokenStore,
	)

	// Initialize providers
	if err := a.loadProviders(); err != nil {
		return errors.Wrap(err, "load providers")
	}

	// Initialize database manager
	switch a.cnf.Database.Type {
	case "sqlite":
		var err error
		a.dbManager, err = dbmanager.NewSQLiteManager(a.cnf.Database.Sqlite.File)
		if err != nil {
			return fmt.Errorf("create sqlite manager: %w", err)
		}
	// case "postgres":
	// 	a.dbManager = dbmanager.NewPostgresDbManager(a.cnf.Db.Host, a.cnf.Db.Port, a.cnf.Db.User, a.cnf.Db.Password, a.cnf.Db.Name)
	// case "mysql":
	// 	a.dbManager = dbmanager.NewMySQLDbManager(a.cnf.Db.Host, a.cnf.Db.Port, a.cnf.Db.User, a.cnf.Db.Password, a.cnf.Db.Name)
	default:
		a.dbManager = dbmanager.NewMemoryDbManager()
	}
	if err := a.dbManager.Connect(); err != nil {
		return fmt.Errorf("connect to database: %w", err)
	}

	a.entry.Info("Services initialized successfully, including authentication and database manager")
	return nil
}

func (a *App) initHandlers() error {

	// Initialize UserModule
	userStore := dbstore.NewUserStore(a.dbManager)
	if err := userStore.CreateTable(); err != nil {
		return fmt.Errorf("failed to create users table: %w", err)
	}
	userService := services.NewUserService(userStore)
	userHandler := handlers.NewUserHandler(userService)
	a.userModule = &UserModule{
		Store:   userStore,
		Service: userService,
		Handler: userHandler,
	}

	// Initialize ClientModule
	clientStore := dbstore.NewClientStore(a.dbManager)
	if err := clientStore.CreateTable(); err != nil {
		return fmt.Errorf("failed to create clients table: %w", err)
	}
	clientService := services.NewClientService(clientStore)
	clientHandler := handlers.NewClientHandler(clientService)
	a.clientModule = &ClientModule{
		Store:   clientStore,
		Service: clientService,
		Handler: clientHandler,
	}

	// Initialize authentication handler
	a.authHandler = handlers.NewAuthHandler(a.authService, a.userModule.Store)

	// Initialize resource handlers
	a.providerHandler = handlers.NewProviderHandler()
	// Initialize other handlers...

	a.entry.Info("Handlers initialized successfully")
	return nil
}

func (a *App) loadProviders() error {
	for name, config := range a.cnf.Providers {
		provider, ok := cloud.GetProvider(name)
		if !ok {
			return fmt.Errorf("provider %s not found", name)
		}
		err := provider.Initialize(config)
		if err != nil {
			return fmt.Errorf("initialize provider %s: %w", name, err)
		}
		a.entry.WithField("provider", name).Info("Provider initialized")
	}
	a.entry.Info("All providers loaded successfully")

	return nil
}

func (a *App) setupRoutes() {
	// API version group
	v1 := a.rtr.Group("/api/v1")

	// Auth routes - no middleware required

	// Public routes (no authentication required)
	public := v1.Group("/")
	public.POST("/users", a.userModule.Handler.CreateUser) // Allow user registration without authentication

	// Auth routes - no middleware required
	public.POST("/login", a.authHandler.Login)                // Allow login without authentication
	public.POST("/refresh-token", a.authHandler.RefreshToken) // Allow token refresh without authentication
	public.POST("/logout", a.authHandler.Logout)              // Allow logout without authentication
	public.GET("/health", func(c *gin.Context) {
		c.JSON(200, gin.H{"status": "ok"})
	})

	// Protected routes - require authentication
	protected := v1.Group("/")
	protected.Use(mw.Auth(a.authService)) // Auth middleware with service dependency

	// Register resource routes
	providers := protected.Group("/providers")
	a.providerHandler.RegisterRoutes(providers)

	clients := protected.Group("/clients")
	clients.GET("/", a.clientModule.Handler.ListClients)
	clients.POST("/", a.clientModule.Handler.CreateClient)
	clients.GET("/:id", a.clientModule.Handler.GetClient)
	clients.PUT("/:id", a.clientModule.Handler.UpdateClient)
	clients.DELETE("/:id", a.clientModule.Handler.DeleteClient)
	clients.GET("/:id/deployments", a.clientModule.Handler.GetClientDeployments)

	users := protected.Group("/users")
	users.GET("/", a.userModule.Handler.ListUsers)
	users.GET("/:id", a.userModule.Handler.GetUser)
	users.PUT("/:id", a.userModule.Handler.UpdateUser)
	users.DELETE("/:id", a.userModule.Handler.DeleteUser)
	users.GET("/:id/deployments", a.userModule.Handler.GetUserDeployments)

	// Register other resource routes...

	a.entry.Info("Routes configured successfully")
}
