package org.initialde.yakasave.Integration;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.initialde.yakasave.Api.Requests.CreateCollectiveSavingsFundRequest;

import org.initialde.yakasave.Api.Requests.LoginRequest;
import org.initialde.yakasave.Infrastructure.Persistence.SavingsFundRepository;
import org.initialde.yakasave.UserFactory;
import org.initialde.yakasave.Infrastructure.Persistence.UserRepository;
import org.initialde.yakasave.Infrastructure.authentication.AuthenticationGateway;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.UUID;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@Transactional
@SpringBootTest
@AutoConfigureMockMvc
public class CreateCollectiveSavingsFundControllerTests {
    private final String ENDPOINT = "/savings-fund/personal/create";
    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private AuthenticationGateway authenticationGateway;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private SavingsFundRepository savingsFundRepository;

    @BeforeEach
    public void setup() {
        savingsFundRepository.deleteAll();
        userRepository.deleteAll();
    }

    @Test
    public void shouldCreateCollectiveSavingsFund() throws Exception {
        final var userCredentials = new LoginRequest("john doe", "toto1234");
        final var user = UserFactory.create( "john doe", "toto1234");
        userRepository.save(user);

        String token = authenticationGateway.authenticate(userCredentials);
        String goalTitle = "Buy a cancer's traitment!";
        double goalAmount = 5000.0;
        String description = "This is a description for a cancer's traitment!";
        LocalDate launchDate = LocalDate.now();
        LocalDate deadline = LocalDate.of(2027, 1, 1);
        String reference = UUID.randomUUID().toString();
        boolean memberApproval = false;
        int maxAllowedMembers = 5;
        var request = new CreateCollectiveSavingsFundRequest(
                goalTitle,
                description,
                goalAmount,
                launchDate,
                deadline,
                reference,
                memberApproval,
                maxAllowedMembers
        );

        this.mockMvc.perform(post(ENDPOINT)
                        .contentType(MediaType.APPLICATION_JSON)
                        .header("Authorization", "Bearer " + token)
                        .content(objectMapper.writeValueAsString(request)))
                .andExpect(status().isOk())
                .andReturn();
    }

    @Test
    public void shouldNotCreateCollectiveSavingsFundWithDeadlineAfterLaunchDate() throws Exception {
        final var userCredentials = new LoginRequest("john doe", "toto1234");
        final var user = UserFactory.create( "john doe", "toto1234");
        userRepository.save(user);

        String token = authenticationGateway.authenticate(userCredentials);
        String goalTitle = "Buy a cancer's traitment!";
        double goalAmount = 5000.0;
        String description = "This is a description for a cancer's traitment!";
        LocalDate launchDate = LocalDate.now();
        LocalDate deadline = LocalDate.of(2022, 1, 1);
        String reference = UUID.randomUUID().toString();
        boolean memberApproval = false;
        int maxAllowedMembers = 5;
        var request = new CreateCollectiveSavingsFundRequest(
                goalTitle,
                description,
                goalAmount,
                launchDate,
                deadline,
                reference,
                memberApproval,
                maxAllowedMembers
        );

        this.mockMvc.perform(post(ENDPOINT)
                        .contentType(MediaType.APPLICATION_JSON)
                        .header("Authorization", "Bearer " + token)
                        .content(objectMapper.writeValueAsString(request)))
                .andExpect(status().isBadRequest())
                .andReturn();
    }
}
