package main

import (
	"context"
	"crypto/subtle"
	"fmt"
	"log"
	"net/http"

	"git.agecem.com/bottin/agendas/ui"
	"git.agecem.com/bottin/bottin/v10/pkg/bottin"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func RunServer(ctx context.Context, cfg Config, bottinClient *bottin.APIClient, dbClient *DBClient) error {
	select {
	case <-ctx.Done():
		return ctx.Err()
	default:
		if bottinClient == nil {
			return fmt.Errorf("nil bottin client")
		}

		if dbClient == nil {
			return fmt.Errorf("nil dbClient")
		}

		if err := dbClient.Init(ctx); err != nil {
			return err
		}

		e := echo.New()

		r := ui.NewRenderer()

		if r == nil {
			return fmt.Errorf("nil renderer")
		}

		e.Renderer = r

		e.Pre(middleware.AddTrailingSlash())

		// basic auth
		if len(cfg.Credentials) == 0 {
			return fmt.Errorf("UI requires at least one credential (config key `Credentials` of type map[string]string)")
		}

		e.Pre(middleware.BasicAuth(
			func(username, password string, c echo.Context) (bool, error) {
				for validUser, validPass := range cfg.Credentials {
					userOK := subtle.ConstantTimeCompare([]byte(username), []byte(validUser)) == 1
					passOK := subtle.ConstantTimeCompare([]byte(password), []byte(validPass)) == 1
					if userOK && passOK {
						// log successful basic auths username
						log.Println("login ok for user", username)

						return true, nil
					}
				}
				return false, nil
			}),
		)

		e.GET("/", UIIndex(ctx, bottinClient, dbClient))
		e.GET("/nothing/", func(c echo.Context) error { return c.NoContent(http.StatusOK) })
		//e.GET("/transaction/", UIReadTransaction
		e.POST("/transaction/", UICreateTransaction(ctx, cfg, bottinClient, dbClient))

		address := fmt.Sprintf(":%d", cfg.Port)

		if cfg.TLS.Enabled {
			return e.StartTLS(address, cfg.TLS.Cert, cfg.TLS.Key)
		} else {
			return e.Start(address)
		}
	}
}