package accountapiimp

import (
	"errors"
	"net/http"

	"github.com/tech/sendico/pkg/api/http/response"
	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/model"
	"github.com/tech/sendico/pkg/mutil/mzap"
	"github.com/tech/sendico/server/interface/api/sresponse"
	"go.uber.org/zap"
)

func (a *AccountAPI) updateProfile(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
	ctx := r.Context()
	// Validate user input
	u, err := a.attemptDecodeAccount(r)
	if err != nil {
		a.logger.Warn("Failed to decide profile update", zap.Error(err))
		return response.Internal(a.logger, a.Name(), err)
	}
	if u.Login == "" {
		a.logger.Debug("No email in request")
		return a.reportEmailMissing()
	}
	if u.Name == "" {
		a.logger.Debug("No name in request")
		return response.BadRequest(a.logger, a.Name(), "name_missing", "name is required")
	}

	if account.Login != u.Login {
		// Change email address
		verificationToken, err := a.accService.UpdateLogin(ctx, account, u.Login)
		if err != nil {
			if errors.Is(err, merrors.ErrDataConflict) {
				a.logger.Debug("Duplicate login, denying change...", zap.Error(err), mzap.StorableRef(u))
				return a.reportDuplicateEmail()
			}
			a.logger.Warn("Error while updating login", zap.Error(err), mzap.StorableRef(u))
			return response.Internal(a.logger, a.Name(), err)
		}

		// Send verification email
		if err = a.sendWelcomeEmail(account, verificationToken); err != nil {
			a.logger.Warn("Failed to send verification email", zap.Error(err), mzap.StorableRef(account))
			return response.Internal(a.logger, a.Name(), err)
		}

	} else {
		// Save the user
		u.Password = account.Password
		u.Status = account.Status
		if err = a.db.Update(ctx, u); err != nil {
			a.logger.Warn("Failed to save account", zap.Error(err), mzap.StorableRef(u))
			return response.Internal(a.logger, a.Name(), err)
		}
	}

	return sresponse.Account(a.logger, u, token)
}
