package enea.lecservice.services.mocks;

import com.fasterxml.jackson.core.type.TypeReference;
import enea.lecservice.models.dto.ServiceResponse;
import enea.lecservice.repository.PermissionRepository;
import enea.lecservice.security.IUserInfoService;
import enea.lecservice.security.dto.UserInfo;
import enea.lecservice.utils.JacksonUtils;
import enea.lecservice.utils.RegexUtils;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import java.nio.file.Files;
import java.security.Principal;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Log4j2
@Profile("dev")
@RequiredArgsConstructor
public class MockedUserInfoService implements IUserInfoService {
    private final PermissionRepository permissionRepository;
    @Override
    public Optional<UserInfo> getUserInfo(String username, String password) {

        try {
            String user = RegexUtils.validSimpleText(username.split("@")[0]);
            String userJson = new String(Files.readAllBytes(ResourceUtils.getFile(String.format("classpath:mocks/login_%s.json", user)).toPath()));
            UserInfo userInfo = JacksonUtils.fromJson(userJson, new TypeReference<UserInfo>() {});

            if (userInfo != null && userInfo.getEmail().equals(username) && "demo".equals(password)) {
                userInfo.setUsername(username);
                userInfo.setPassword(password);
                fillPermissionsByRoles(userInfo);
                return Optional.of(userInfo);
            }
        }
        catch (Exception ex) {
            // TODO: If response codes should be managed, handle them here!
            log.error(ex);
        }

        return Optional.empty();
    }

    private void fillPermissionsByRoles(UserInfo userInfo) {
        var roles = userInfo.getUserroles().stream().map(UserInfo.RoleDTO::getRoleName).collect(Collectors.toList());
        var permissions = permissionRepository.findPermissionsByRolesDescription(roles);
        userInfo.setPermissions(permissions);
    }

    @Override
    public Optional<UserInfo> getUserInfo(Principal principal) {
        UserInfo userInfo = (UserInfo) ((UsernamePasswordAuthenticationToken) principal).getPrincipal();
        if (userInfo != null)
            return Optional.of(userInfo);

        return Optional.empty();
    }

    @Override
    public ServiceResponse logout(UserInfo userInfo) {
        if (userInfo == null || userInfo.getToken() == null || (userInfo.getToken().getValue() == null && userInfo.getToken().getValue().isEmpty()))
            return ServiceResponse.Error("Fornisci un token valido!");

        return ServiceResponse.Success();
    }

	@Override
	public Optional<UserInfo> getUserInfo(String token) {
		// TODO Auto-generated method stub
		return Optional.empty();
	}
}
