package routers

import (
	"crypto/rand"
	"strings"

	"github.com/go-chi/chi/v5"
	api "github.com/tech/sendico/pkg/api/http"
	"github.com/tech/sendico/pkg/db/account"
	"github.com/tech/sendico/pkg/db/confirmation"
	"github.com/tech/sendico/pkg/db/refreshtokens"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/mservice"
	"github.com/tech/sendico/server/interface/api/sresponse"
	"github.com/tech/sendico/server/interface/middleware"
	re "github.com/tech/sendico/server/internal/api/routers/endpoint"
	"github.com/tech/sendico/server/internal/server/confirmationimp"
)

type PublicRouter struct {
	logger    mlogger.Logger
	db        account.DB
	cdb       confirmation.DB
	cstore    *confirmationimp.ConfirmationStore
	imp       *re.HttpEndpointRouter
	rtdb      refreshtokens.DB
	config    middleware.TokenConfig
	signature middleware.Signature
	service   mservice.Type
}

func (pr *PublicRouter) InstallHandler(service mservice.Type, endpoint string, method api.HTTPMethod, handler sresponse.HandlerFunc) {
	pr.imp.InstallHandler(service, endpoint, method, handler)
}

func (pr *PublicRouter) generateCode() (string, error) {
	const digits = "0123456789"
	b := make([]byte, confirmationimp.DefaultConfig().CodeLength)
	if _, err := rand.Read(b); err != nil {
		return "", err
	}
	for i := range b {
		b[i] = digits[int(b[i])%len(digits)]
	}
	return string(b), nil
}

func (pr *PublicRouter) maskEmail(email string) string {
	parts := strings.Split(email, "@")
	if len(parts) != 2 {
		return email
	}
	local := parts[0]
	if len(local) > 2 {
		local = local[:1] + "***" + local[len(local)-1:]
	} else {
		local = local[:1] + "***"
	}
	return local + "@" + parts[1]
}

func NewRouter(logger mlogger.Logger, apiEndpoint string, db account.DB, cdb confirmation.DB, rtdb refreshtokens.DB, router chi.Router, config *middleware.TokenConfig, signature *middleware.Signature) *PublicRouter {
	l := logger.Named("public")
	hr := PublicRouter{
		logger:    l,
		db:        db,
		cdb:       cdb,
		cstore:    confirmationimp.NewStore(cdb),
		rtdb:      rtdb,
		config:    *config,
		signature: *signature,
		imp:       re.NewHttpEndpointRouter(l, apiEndpoint, router, config, signature),
		service:   mservice.Accounts,
	}

	hr.InstallHandler(hr.service, "/login", api.Post, hr.login)
	hr.InstallHandler(hr.service, "/rotate", api.Post, hr.rotateRefreshToken)
	hr.InstallHandler(hr.service, "/refresh", api.Post, hr.refreshAccessToken)

	return &hr
}
