package app

import (
	"context"

	"git.optclblast.xyz/draincloud/draincloud-core/internal/app/handlers"
	filesengine "git.optclblast.xyz/draincloud/draincloud-core/internal/files_engine"
	"git.optclblast.xyz/draincloud/draincloud-core/internal/processor"
	resolvedispatcher "git.optclblast.xyz/draincloud/draincloud-core/internal/resolve_dispatcher"
	"git.optclblast.xyz/draincloud/draincloud-core/internal/resolvers/auth"
	"git.optclblast.xyz/draincloud/draincloud-core/internal/storage"
	"github.com/gin-gonic/gin"
)

type DrainCloud struct {
	mux         *gin.Engine
	database    storage.Database
	filesEngine *filesengine.FilesEngine

	ginProcessor processor.Processor[gin.HandlerFunc]
}

func New(
	ctx context.Context,
	database storage.Database,
	filesEngine *filesengine.FilesEngine,
) *DrainCloud {
	mux := gin.Default()

	dispatcher := resolvedispatcher.New()
	dispatcher.RegisterResolver(
		ctx,
		auth.AuthResolverV1Name,
		auth.NewAuthResolver(database),
	)

	d := &DrainCloud{
		database:     database,
		filesEngine:  filesEngine,
		ginProcessor: processor.NewGinProcessor(database, dispatcher),
	}

	// TODO. Maybe overkill
	internalGroup := mux.Group("/_internal")
	{
		regGroup := internalGroup.Group("/register")
		{
			regGroup.POST("/resolver", d.ginProcessor.Process(
				handlers.NewInternalRegisterResolverHandler(dispatcher),
			))
			regGroup.POST("/plugin", func(ctx *gin.Context) {})
		}

		
	}

	// Built-in auth component of DrainCloud-Core
	authGroup := mux.Group("/auth")
	{
		authGroup.POST("/register", d.ginProcessor.Process(
			handlers.NewRegisterHandler(database),
		))
		authGroup.POST("/logon", d.ginProcessor.Process(
			handlers.NewLogonHandler(database),
		))
	}

	filesGroup := mux.Group("/files")
	{
		filesGroup.POST("/upload", d.ginProcessor.Process(
			handlers.NewUploadFileHandler(filesEngine),
		))
	}

	d.mux = mux

	return d
}

func (d *DrainCloud) Run(ctx context.Context) error {
	return d.mux.Run()
}
