package org.sagebionetworks.bridge.sdk.integration;

import okhttp3.ResponseBody;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.sagebionetworks.bridge.rest.api.ForConsentedUsersApi;
import org.sagebionetworks.bridge.rest.model.Message;
import org.sagebionetworks.bridge.rest.model.ParticipantFile;
import org.sagebionetworks.bridge.rest.model.ParticipantFileList;
import org.sagebionetworks.bridge.user.TestUserHelper;
import org.sagebionetworks.bridge.user.TestUserHelper.TestUser;

import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Scanner;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

public class ParticipantFileTest {

    static final String TEST_UPLOAD_STRING = "This text uploaded as an object via presigned URL.";

    TestUser participant;

    ForConsentedUsersApi userApi;

    ParticipantFile file;

    @Before
    public void before() throws Exception {
        participant = TestUserHelper.createAndSignInUser(ParticipantFileTest.class, true);
        userApi = participant.getClient(ForConsentedUsersApi.class);
    }

    @After
    public void after() throws Exception {
        List<ParticipantFile> remainder = userApi.getParticipantFiles(null, 10).execute().body().getItems();
        while (!remainder.isEmpty()) {
            for (ParticipantFile file : remainder) {
                userApi.deleteParticipantFile(file.getFileId()).execute();
            }
            remainder = userApi.getParticipantFiles(null, 10).execute().body().getItems();
        }
        participant.signOutAndDeleteUser();
    }

    @Test
    public void crudParticipantFile() throws Exception {
        file = new ParticipantFile();
        file.setMimeType("text/plain");

        ForConsentedUsersApi userApi = participant.getClient(ForConsentedUsersApi.class);

        final ParticipantFile keys = userApi.createParticipantFile("file_id", file).execute().body();

        assertNotNull(keys);
        assertEquals(file.getMimeType(), keys.getMimeType());
        String uploadUrl = keys.getUploadUrl();

        URL url = new URL(uploadUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("PUT");
        connection.setRequestProperty("Content-Type", "text/plain");
        OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
        out.write(TEST_UPLOAD_STRING);
        out.close();
        assertEquals(200, connection.getResponseCode());;
        connection.disconnect();
        
        ParticipantFileList results = userApi.getParticipantFiles(null, 5).execute().body();
        assertNotNull(results);
        List<ParticipantFile> resultList = results.getItems();
        assertEquals(1, resultList.size());
        ParticipantFile onlyFile = resultList.get(0);
        assertEquals("text/plain", onlyFile.getMimeType());
        assertEquals("file_id", onlyFile.getFileId());

        for (int i = 0; i < 5; i++) {
            file = new ParticipantFile();
            file.setMimeType("text/plain");
            userApi.createParticipantFile(i + "file", file).execute();
        }
        
        // Note: After starting a local Bridge server, this test fails with a 403 Forbidden. 
        // Thereafter is seems to consistently succeed. It is not a DDB eventual consistency
        // issue.
        ResponseBody body = userApi.getParticipantFile("file_id").execute().body();
        assertNotNull(body);
        assertNotNull(body.contentType());
        assertEquals("text/plain", body.contentType().toString());
        assertEquals(TEST_UPLOAD_STRING.length(), body.contentLength());
        try (InputStream content = body.byteStream(); Scanner sc = new Scanner(content)) {
            assertEquals("This text uploaded as an object via presigned URL.", sc.nextLine());
        }

        results = userApi.getParticipantFiles(null, 5).execute().body();
        assertNotNull(results);
        resultList = results.getItems();
        assertEquals(5, resultList.size());
        String nextKey = results.getNextPageOffsetKey();
        results = userApi.getParticipantFiles(nextKey, 5).execute().body();
        assertNotNull(results);
        resultList = results.getItems();
        assertEquals(1, resultList.size());
        assertNull(results.getNextPageOffsetKey());

        Message deleteMessage = userApi.deleteParticipantFile("file_id").execute().body();
        assertNotNull(deleteMessage);
        assertEquals("Participant file deleted.", deleteMessage.getMessage());

        for (int i = 0; i < 5; i++) {
            userApi.deleteParticipantFile(i + "file").execute();
        }

        results = userApi.getParticipantFiles(null, 5).execute().body();
        assertNotNull(results);
        resultList = results.getItems();
        assertEquals(0, resultList.size());
    }
}
@@ -212,16 +212,90 @@
 ersApi;%0A
+import org.sagebionetworks.bridge.rest.exceptions.InvalidEntityException;%0A
 import o
@@ -340,16 +340,16 @@
 essage;%0A
-
 import o
@@ -890,16 +890,53 @@
 ertNull;
+%0Aimport static org.junit.Assert.fail;
 %0A%0Apublic
@@ -1869,24 +1869,438 @@
 r();%0A    %7D%0A%0A
+    @Test%0A    public void invalidParticipantFileRejected() throws Exception %7B%0A        file = new ParticipantFile();%0A%0A        try %7B%0A            userApi.createParticipantFile(%22file_id%22, file).execute().body();%0A            fail(%22Should have thrown an exception%22);%0A        %7D catch(InvalidEntityException e) %7B%0A            assertEquals(%22mimeType is required%22, e.getErrors().get(%22mimeType%22).get(0));%0A        %7D%0A    %7D%0A    %0A
     @Test%0A  

Add test for validation (yes it's there)