package com.MedInsuranceV2.Version20.Email;
// Import your User model class
import org.springframework.stereotype.Service;

import com.MedInsuranceV2.Version20.User.User;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Service
public class OtpService {

    // In a real application, consider using a more robust solution for OTP storage
    // like a dedicated cache (e.g., Guava Cache, Caffeine, Redis) or a database
    // for production use cases, especially for scalability and persistence.
    // The current HashMap is in-memory and will lose data on application restart.
    private static final Map<String, OtpEntry> otpStore = new HashMap<>();
    private static final long OTP_VALIDITY_MS = 5 * 60 * 1000; // OTP valid for 5 minutes

    // Inner class to hold OTP, its expiry time, and the pending User object
    private static class OtpEntry {
        String otp;
        long expiryTime;
        User pendingUser; // This field stores the User object associated with the OTP

        public OtpEntry(String otp, long expiryTime, User pendingUser) {
            this.otp = otp;
            this.expiryTime = expiryTime;
            this.pendingUser = pendingUser;
        }
    }

    /**
     * Generates a 6-digit OTP, stores it in memory along with its expiry time
     * and the associated User object, and returns the generated OTP.
     * The OTP is stored using the user's email as the key.
     *
     * @param email The email ID for which the OTP is generated.
     * @param user The User object representing the pending registration.
     * @return The generated OTP string.
     */
    public String generateAndStoreOtp(String email, User user) {
        // Generate a 6-digit random OTP
        String otp = String.format("%06d", new Random().nextInt(1000000)); // Ensures 6 digits, e.g., 000123

        // Calculate expiry time
        long expiryTime = System.currentTimeMillis() + OTP_VALIDITY_MS;

        // Store the OTP entry (OTP, expiry time, and the pending User object)
        otpStore.put(email, new OtpEntry(otp, expiryTime, user));

        System.out.println("Generated OTP for " + email + ": " + otp + " (Valid until: " + new java.util.Date(expiryTime) + ")"); // For debugging
        return otp;
    }

    /**
     * Validates an entered OTP against the stored OTP for a given email.
     * Checks for existence and expiry.
     *
     * @param email The email ID to validate the OTP against.
     * @param enteredOtp The OTP entered by the user.
     * @return true if the OTP is valid and not expired, false otherwise.
     */
    public boolean validateOtp(String email, String enteredOtp) {
        OtpEntry storedOtpEntry = otpStore.get(email);

        if (storedOtpEntry == null) {
            System.out.println("Validation failed for " + email + ": No OTP found.");
            return false; // No OTP or pending user for this email
        }

        if (System.currentTimeMillis() > storedOtpEntry.expiryTime) {
            otpStore.remove(email); // Remove expired OTP and its associated user data
            System.out.println("Validation failed for " + email + ": OTP expired.");
            return false; // OTP expired
        }

        boolean isValid = storedOtpEntry.otp.equals(enteredOtp);
        if (!isValid) {
            System.out.println("Validation failed for " + email + ": OTP mismatch. Expected " + storedOtpEntry.otp + ", Got " + enteredOtp);
        } else {
            System.out.println("Validation successful for " + email);
        }
        return isValid;
    }

    /**
     * Retrieves the pending User object associated with an email, if the OTP is still valid.
     * This is used by the RegistrationService to get the user data for final saving.
     *
     * @param email The email ID to retrieve the pending user for.
     * @return The pending User object if found and OTP is still valid, null otherwise.
     */
    public User getPendingUser(String email) {
        OtpEntry storedOtpEntry = otpStore.get(email);
        if (storedOtpEntry != null && System.currentTimeMillis() <= storedOtpEntry.expiryTime) {
            System.out.println("Retrieved pending user for " + email);
            return storedOtpEntry.pendingUser;
        }
        System.out.println("Could not retrieve pending user for " + email + ": OTP expired or not found.");
        return null; // OTP expired or not found
    }

    /**
     * Removes the OTP and its associated User data from storage for a given email.
     * This should be called after successful OTP verification or if the OTP is no longer needed.
     *
     * @param email The email ID for which to remove the OTP.
     */
    public void removeOtp(String email) {
        otpStore.remove(email);
        System.out.println("Removed OTP and pending user data for " + email);
    }

	public void clearOtp(String emailId) {
		// Clear the OTP entry for the given email ID
		otpStore.remove(emailId);
		System.out.println("Cleared OTP for " + emailId); // For debugging
		
	}
}
