package edu.prlab.tyler.iotgateway.gateway;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.prlab.tyler.iotgateway.cloud.pojo.auth.SensitiveUser;
import edu.prlab.tyler.iotgateway.cloud.pojo.device.Device;
import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyChoice;
import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyContent;
import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyPolicyReport;
import edu.prlab.tyler.iotgateway.gateway.pojo.auth.User;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = GatewayApplication.class)
public class GatewayHttpApiTest {

    @Autowired
    WebApplicationContext context;

    private MockMvc mvc;
    private ObjectMapper mapper;

    @Before
    public void setup() {
        this.mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .build();
        this.mapper = new ObjectMapper();
    }

    @Test
    public void getPrivacyPolicyAndSetChoice() throws Exception {

        //登入預設帳號
        MvcResult result = mvc.perform(MockMvcRequestBuilders
                .post("/login")
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .content(mapper.writeValueAsString(User.builder().username("testUser0").password("testUser0").build())))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        Assert.assertNotNull(result);

        //取得裝置清單
        result = mvc.perform(MockMvcRequestBuilders
                .get("/device")
                .accept(MediaType.APPLICATION_JSON_UTF8))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        Iterable<Device> devices = mapper.readValue(result.getResponse().getContentAsString(),
                new TypeReference<Iterable<Device>>() {
                });
        Assert.assertNotNull(devices);

        //綁定裝置
        result = mvc.perform(MockMvcRequestBuilders
                .post("/device/" + "a1252c49-4188-4e6d-a32e-66604c664fb8")
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .content(mapper.writeValueAsString(User.builder().username("testUser0").password("testUser0").build())))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        Device device= mapper.readValue(result.getResponse().getContentAsString(), Device.class);
        Assert.assertNotNull(device);

        //拿取隱私政策
        result = mvc.perform(MockMvcRequestBuilders
                .get("/privacy/" + "a1252c49-4188-4e6d-a32e-66604c664fb8")
                .accept(MediaType.APPLICATION_JSON_UTF8))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        PrivacyPolicyReport report = mapper.readValue(result.getResponse().getContentAsString(), PrivacyPolicyReport.class);
        Assert.assertNotNull(report);

        //表達隱私偏好
        device = report.getDevice();
        PrivacyChoice privacyChoice = PrivacyChoice.builder()
                .privacyContent(PrivacyContent.builder()
                        .user(SensitiveUser.builder()
                                .username("test")
                                .password("test")
                                .build())
                        .device(device)
                        .policy(report.getPolicies().get(0))
                        .build())
                .isAccepted(true)
                .build();
        mapper.writeValueAsString(privacyChoice);
        result = mvc.perform(MockMvcRequestBuilders
                .post("/choice")
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .accept(MediaType.APPLICATION_JSON_UTF8)
                .content(mapper.writeValueAsString(privacyChoice)))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        Assert.assertNotNull(result);

        //取得所有隱私偏好
        result = mvc.perform(MockMvcRequestBuilders
                .get("/choice")
                .accept(MediaType.APPLICATION_JSON_UTF8))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
        Assert.assertNotNull(result);
    }
}
