package resource

import (
	"context"
	"net/http"

	"github.com/aarondl/opt/omit"
	"github.com/rs/zerolog/log"
	"source.gleipnir.technology/Gleipnir/nidus-sync/auth"
	nhttp "source.gleipnir.technology/Gleipnir/nidus-sync/http"
	"source.gleipnir.technology/Gleipnir/nidus-sync/platform"
)

func Impersonation(r *router) *impersonationR {
	return &impersonationR{
		router: r,
	}
}

type impersonationR struct {
	router *router
}
type impersonation struct {
	UserID omit.Val[int] `json:"id"`
}

func (res *impersonationR) Create(ctx context.Context, r *http.Request, u platform.User, i impersonation) (*impersonation, *nhttp.ErrorWithStatus) {
	if i.UserID.IsUnset() {
		return nil, nhttp.NewBadRequest("you must provide an 'id'")
	}
	target_id := i.UserID.MustGet()
	l, err := platform.ImpersonationCreate(ctx, u, target_id)
	if err != nil {
		return nil, nhttp.NewError("create impersonation: %w", err)
	}
	auth.ImpersonateUser(ctx, target_id)
	log.Info().Int("user.id", u.ID).Str("username", u.Username).Int("target.id", target_id).Int32("log.id", l.ID).Msg("Impersonation begins")
	return &impersonation{
		UserID: i.UserID,
	}, nil
}
func (res *impersonationR) Delete(ctx context.Context, r *http.Request, u platform.User) *nhttp.ErrorWithStatus {
	if auth.ImpersonatedUser == nil {
		return nhttp.NewBadRequest("not impersonating")
	}
	real_user_id := auth.ImpersonatorID(ctx)
	if real_user_id == nil {
		return nhttp.NewError("No impersonator ID")
	}
	err := platform.ImpersonationEnd(ctx, u, *real_user_id)
	if err != nil {
		return nhttp.NewError("end impersonation: %w", err)
	}
	auth.ImpersonateEnd(ctx)
	return nil
}
