/*
 * Retrieves the currently logged-in user from the security context.
 *
 * Author: Harkamal
 * Date: April 2026
 */

package com.petshop.backend.util;

import com.petshop.backend.entity.User;
import com.petshop.backend.repository.UserRepository;
import com.petshop.backend.security.AppPrincipal;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class AuthenticationHelper {

    private final UserRepository userRepository;

    public AuthenticationHelper(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public static Authentication getAuthentication() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new AuthenticationCredentialsNotFoundException("No authenticated user found");
        }
        return authentication;
    }

    public static AppPrincipal getAuthenticatedPrincipal() {
        Object principal = getAuthentication().getPrincipal();
        if (principal instanceof AppPrincipal appPrincipal) {
            return appPrincipal;
        }
        throw new AuthenticationServiceException("Authenticated principal is not supported");
    }

    public static Long getAuthenticatedUserId() {
        return getAuthenticatedPrincipal().getUserId();
    }

    public static User.Role getAuthenticatedRole() {
        return getAuthenticatedPrincipal().getRole();
    }

    public static boolean isCustomer() {
        return getAuthenticatedPrincipal().getRole() == User.Role.CUSTOMER;
    }

    public User getAuthenticatedUser() {
        return getAuthenticatedUser(userRepository);
    }

    public Long getCustomerIdOrNull() {
        if (!isCustomer()) {
            return null;
        }
        return getAuthenticatedUser().getId();
    }

    public Long getEffectiveCustomerId(Long requestedCustomerId) {
        return isCustomer() ? getAuthenticatedUser().getId() : requestedCustomerId;
    }

    public static User getAuthenticatedUser(UserRepository userRepository) {
        Authentication authentication = getAuthentication();
        Object principal = authentication.getPrincipal();

        if (principal instanceof AppPrincipal appPrincipal) {
            return userRepository.findById(appPrincipal.getUserId())
                    .orElseThrow(() -> new UsernameNotFoundException("User not found: " + appPrincipal.getUserId()));
        }

        String username = authentication.getName();
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
    }
}
