package org.sagebionetworks.download.worker;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.sagebionetworks.repo.model.util.AccessControlListUtil.createResourceAccess;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.sagebionetworks.AsynchronousJobWorkerHelper;
import org.sagebionetworks.repo.manager.UserManager;
import org.sagebionetworks.repo.model.ACCESS_TYPE;
import org.sagebionetworks.repo.model.AccessControlListDAO;
import org.sagebionetworks.repo.model.AuthorizationConstants.BOOTSTRAP_PRINCIPAL;
import org.sagebionetworks.repo.model.EntityType;
import org.sagebionetworks.repo.model.Node;
import org.sagebionetworks.repo.model.NodeDAO;
import org.sagebionetworks.repo.model.UserInfo;
import org.sagebionetworks.repo.model.auth.NewUser;
import org.sagebionetworks.repo.model.dao.FileHandleDao;
import org.sagebionetworks.repo.model.dbo.file.download.v2.DownloadListDAO;
import org.sagebionetworks.repo.model.download.AvailableFilesRequest;
import org.sagebionetworks.repo.model.download.DownloadListItem;
import org.sagebionetworks.repo.model.download.DownloadListItemResult;
import org.sagebionetworks.repo.model.download.DownloadListQueryRequest;
import org.sagebionetworks.repo.model.download.DownloadListQueryResponse;
import org.sagebionetworks.repo.model.file.FileHandle;
import org.sagebionetworks.repo.model.helper.AccessControlListObjectHelper;
import org.sagebionetworks.repo.model.helper.DaoObjectHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = { "classpath:test-context.xml" })
public class DownloadListQueryWorkerIntegrationTest {

	public static final long MAX_WAIT_MS = 1000 * 30;

	@Autowired
	private UserManager userManager;
	@Autowired
	private DownloadListDAO downloadListDao;
	@Autowired
	private DaoObjectHelper<Node> nodeDaoHelper;
	@Autowired
	private NodeDAO nodeDao;
	@Autowired
	private DaoObjectHelper<FileHandle> fileHandleDaoHelper;
	@Autowired
	private FileHandleDao fileHandleDao;
	@Autowired
	private AccessControlListObjectHelper aclHelper;
	@Autowired
	private AccessControlListDAO aclDao;

	@Autowired
	AsynchronousJobWorkerHelper asynchronousJobWorkerHelper;

	UserInfo adminUser;
	UserInfo user;

	@BeforeEach
	public void before() {
		aclDao.truncateAll();
		nodeDao.truncateAll();
		fileHandleDao.truncateTable();
		downloadListDao.truncateAllData();

		adminUser = userManager.getUserInfo(BOOTSTRAP_PRINCIPAL.THE_ADMIN_USER.getPrincipalId());
		boolean acceptsTermsOfUse = true;
		String userName = UUID.randomUUID().toString();
		user = userManager.createOrGetTestUser(adminUser,
				new NewUser().setUserName(userName).setEmail(userName + "@foo.org"), acceptsTermsOfUse);
	}

	@AfterEach
	public void after() {
		aclDao.truncateAll();
		nodeDao.truncateAll();
		fileHandleDao.truncateTable();
		downloadListDao.truncateAllData();
		if (user != null) {
			userManager.deletePrincipal(adminUser, user.getId());
		}
	}

	@Test
	public void testQueryWorker() throws Exception {
		Node file = createFileHierarchy();
		List<DownloadListItem> batch = Arrays.asList(new DownloadListItem().setFileEntityId(file.getId()));
		downloadListDao.addBatchOfFilesToDownloadList(user.getId(), batch);

		DownloadListQueryRequest request = new DownloadListQueryRequest()
				.setAvailableFilesRequest(new AvailableFilesRequest());
		// call under test
		asynchronousJobWorkerHelper.assertJobResponse(user, request, (DownloadListQueryResponse response) -> {
			assertNotNull(response);
			assertNotNull(response.getAvailableFiles());
			assertNotNull(response.getAvailableFiles().getPage());
			List<DownloadListItemResult> page = response.getAvailableFiles().getPage();
			assertEquals(1, page.size());
			DownloadListItemResult item = page.get(0);
			assertEquals(file.getId(), item.getFileEntityId());
		}, MAX_WAIT_MS);
	}

	/**
	 * Helper to create a single file in a project with an ACL that grants download
	 * to the user.
	 * 
	 * @return
	 */
	public Node createFileHierarchy() {
		Node project = nodeDaoHelper.create((n) -> {
			n.setNodeType(EntityType.project);
			n.setName("project");
		});
		aclHelper.create((a) -> {
			a.setId(project.getId());
			a.getResourceAccess().add(createResourceAccess(user.getId(), ACCESS_TYPE.DOWNLOAD));
		});
		FileHandle fh = fileHandleDaoHelper.create((f) -> {
			f.setFileName("someFile");
			f.setContentSize(123L);
		});
		Node file = nodeDaoHelper.create((n) -> {
			n.setParentId(project.getId());
			n.setNodeType(EntityType.file);
			n.setName("FileName");
			n.setFileHandleId(fh.getId());
		});
		return file;
	}

}

@@ -2123,16 +2123,61 @@
 00 * 30;
+%0A%09%0A%09public static final int MAX_RETRIES = 25;
 %0A%0A%09@Auto
@@ -3767,16 +3767,47 @@
 equest()
+.setInlcudeAvailableFiles(true)
 %0A%09%09%09%09.se
@@ -4348,16 +4348,29 @@
 _WAIT_MS
+, MAX_RETRIES
 );%0A%09%7D%0A%0A%09

fix for test