package transcode

import (
	"context"

	"scrabble/gateway/internal/backendclient"
	fb "scrabble/pkg/fbs/scrabblefb"
)

// Account linking & merge message types. The email ops carry the costly-
// email rate flag; the telegram ops validate Login Widget data through the
// connector (registered only when the connector is configured). All are
// authenticated. The merge ops are the explicit irreversible step, gated in the UI
// after a merge_required confirm.
const (
	MsgLinkEmailRequest  = "link.email.request"
	MsgLinkEmailConfirm  = "link.email.confirm"
	MsgLinkEmailMerge    = "link.email.merge"
	MsgLinkTelegram      = "link.telegram.confirm"
	MsgLinkTelegramMerge = "link.telegram.merge"
)

// registerLinkOps adds the linking & merge operations. The telegram ops need the
// connector's Login Widget validator, so they are registered only when tg is set.
func registerLinkOps(r *Registry, backend *backendclient.Client, tg TelegramValidator) {
	r.ops[MsgLinkEmailRequest] = Op{Handler: linkEmailRequestHandler(backend), Auth: true, Email: true}
	r.ops[MsgLinkEmailConfirm] = Op{Handler: linkEmailConfirmHandler(backend), Auth: true, Email: true}
	r.ops[MsgLinkEmailMerge] = Op{Handler: linkEmailMergeHandler(backend), Auth: true, Email: true}
	if tg != nil {
		r.ops[MsgLinkTelegram] = Op{Handler: linkTelegramHandler(backend, tg, false), Auth: true}
		r.ops[MsgLinkTelegramMerge] = Op{Handler: linkTelegramHandler(backend, tg, true), Auth: true}
	}
}

func linkEmailRequestHandler(backend *backendclient.Client) Handler {
	return func(ctx context.Context, req Request) ([]byte, error) {
		in := fb.GetRootAsLinkEmailRequest(req.Payload, 0)
		if err := backend.LinkEmailRequest(ctx, req.UserID, string(in.Email())); err != nil {
			return nil, err
		}
		return encodeAck(true), nil
	}
}

func linkEmailConfirmHandler(backend *backendclient.Client) Handler {
	return func(ctx context.Context, req Request) ([]byte, error) {
		in := fb.GetRootAsLinkEmailConfirm(req.Payload, 0)
		res, err := backend.LinkEmailConfirm(ctx, req.UserID, string(in.Email()), string(in.Code()))
		if err != nil {
			return nil, err
		}
		return encodeLinkResult(res), nil
	}
}

func linkEmailMergeHandler(backend *backendclient.Client) Handler {
	return func(ctx context.Context, req Request) ([]byte, error) {
		in := fb.GetRootAsLinkEmailConfirm(req.Payload, 0)
		res, err := backend.LinkEmailMerge(ctx, req.UserID, string(in.Email()), string(in.Code()))
		if err != nil {
			return nil, err
		}
		return encodeLinkResult(res), nil
	}
}

// linkTelegramHandler validates Login Widget data via the connector and then calls
// the backend's link or merge endpoint with the trusted Telegram external id.
func linkTelegramHandler(backend *backendclient.Client, tg TelegramValidator, merge bool) Handler {
	return func(ctx context.Context, req Request) ([]byte, error) {
		in := fb.GetRootAsLinkTelegramRequest(req.Payload, 0)
		user, err := tg.ValidateLoginWidget(ctx, string(in.Data()))
		if err != nil {
			return nil, err
		}
		var res backendclient.LinkResultResp
		if merge {
			res, err = backend.LinkTelegramMerge(ctx, req.UserID, user.ExternalID)
		} else {
			res, err = backend.LinkTelegram(ctx, req.UserID, user.ExternalID)
		}
		if err != nil {
			return nil, err
		}
		return encodeLinkResult(res), nil
	}
}
