package services_astrologer

import (
	"time"

	"astrology-api/services"
)

// Astrologer-side OTP values and delivery.
//
// Everything here now delegates to the user-side `services` package, which is
// where the SMS gateway configuration lives. The two stacks keep their own
// controllers, services and repositories, but there is only one MSG91 account
// and one APP_ENV, so resolving them twice only created somewhere for the two
// copies to drift apart - and they had: this file read APP_ENV directly while
// the user side compared it against a package variable that was initialised
// before the .env file was ever loaded.

// StaticOTP is the OTP every non-production environment issues, so the app can
// be exercised end to end without an SMS or an email round trip.
const StaticOTP = services.StaticOTP

const (
	// MaxOTPAttempts bounds wrong guesses within one OTP window.
	MaxOTPAttempts = 5

	// MaxOTPResends bounds resends within one OTP window. The counter is cleared
	// once the window lapses, so a stale count cannot lock an account out for
	// good the way a never-reset counter did.
	MaxOTPResends = 5
)

// OTPExpiry is how long a mobile or email OTP stays usable.
//
// A function rather than a constant now, because the window is configurable
// from the systemflag table (Msg91OtpExpiryMinutes).
func OTPExpiry() time.Duration {

	return services.OTPExpiry()
}

// OTPExpirySeconds is the same window in the unit the API reports.
func OTPExpirySeconds() int {

	return int(services.OTPExpiry().Seconds())
}

// IsProduction reports whether APP_ENV names the production environment.
//
// Everything else - development, staging, an unset value - counts as non
// production and gets the static OTP, which is the state a developer or a QA
// build is in.
func IsProduction() bool {

	return services.IsProduction()
}

// NewOTP is the single place an astrologer OTP comes from.
//
// Production gets a fresh random value that is delivered over MSG91 or OTPLESS;
// every other environment gets the static code.
func NewOTP() (string, error) {

	return services.NewOTP()
}

// DeliverMobileOTP sends the mobile OTP, and does nothing outside production.
//
// Delivery is best effort and is called after the transaction has committed: the
// OTP is already stored, so a carrier failure must not undo the registration or
// the login. Failures are logged, and the astrologer can ask for another one
// with /resend-otp.
func DeliverMobileOTP(mobile string, otp string) {

	services.DeliverMobileOTP(mobile, otp)
}

// DeliverEmailOTP sends the email OTP, on the same best effort terms as
// DeliverMobileOTP.
func DeliverEmailOTP(email string, otp string) {

	services.DeliverEmailOTP(email, otp)
}

// echoOTP decides whether the OTP may appear in the response body.
//
// The login and resend responses carry an `otp` field, which the app reads to
// prefill the verify screen during development. In production that field made
// the whole OTP pointless: POST /api/astrologer/login with somebody's mobile
// number answered with their live code, and /verify-login then handed out their
// tokens. It is blanked outside development.
func echoOTP(otp string) string {

	if services.IsProduction() {
		return ""
	}

	return otp
}
