package com.example.cezenPBX.config;

import com.example.cezenPBX.DAO.UserOpsDAO;
import com.example.cezenPBX.entity.user.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class CustomAuthenticationProviderForCezen implements AuthenticationProvider {

    @Autowired
    private UserOpsDAO userOpsDAO;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        //get credentials from login form
        String username = authentication.getName();
        String pwd = authentication.getCredentials().toString();

        //sanity check
        if (username.isEmpty() || pwd.isEmpty()) return null;

        //check for employee
        UserEntity user = null;
        try {
            //check if employee exists if yes then fetch details
            user = this.userOpsDAO.getUserByUserName(username);
        } catch (Exception e) {
            System.out.println(e.toString());
            return null;
        }

        if (passwordEncoder.matches(pwd, user.getPassword())) {

            //then it is a match a number of springs granted authorities
            List<GrantedAuthority> authorities = new ArrayList<>();

            //loop through the users authorities and add each of them to simple granted authority
            try {
                //check if user is part of permission set for admin signing in
                boolean isAdmin = false;
                for(var permission : user.getRoles()){
                    if(permission.getRole().equals("ROLE_admin")) isAdmin = true;
                }
                if(!isAdmin) throw new BadCredentialsException("no employee permission for given employee");

                user.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole())));
            } catch (Exception e) {
                //use/**/r doesn't have permissions or roles = null
                System.out.println(e.toString());
                return null;
            }

            return new UsernamePasswordAuthenticationToken(user.getUserName(), pwd, authorities);
        } else {
            throw new BadCredentialsException("Invalid password!");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        //tells spring that i want to support username password style of auth
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }

}
