package com.iqser.red.service.peristence.v1.server.integration.tests;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierStatusClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierStatusRequest;

import feign.FeignException;

public class DossierStatusTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private DossierStatusClient dossierStatusClient;

    @Autowired
    private DossierClient dossierClient;

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;


    @Test
    public void testDossierStatus() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var allDossierStatus = dossierStatusClient.getAllDossierStatusForTemplate(dossierTemplate.getId());

        assertThat(allDossierStatus.size()).isZero();

        // Create first state
        var crudsr = new DossierStatusRequest();
        crudsr.setName("name1");
        crudsr.setColor("#cccccc");
        crudsr.setDescription("description1");
        crudsr.setDossierTemplateId(dossierTemplate.getId());

        var loadedDossierStatus = dossierStatusClient.createOrUpdateDossierStatus(crudsr);
        assertThat(loadedDossierStatus).isNotNull();
        assertThat(loadedDossierStatus.getDossierCount()).isNull();
        assertThat(loadedDossierStatus.getRank()).isEqualTo(crudsr.getRank());

        // update first state
        crudsr.setDossierStatusId(loadedDossierStatus.getId());
        crudsr.setDescription("New Description");
        crudsr.setRank(1);
        var updatedStatus = dossierStatusClient.createOrUpdateDossierStatus(crudsr);
        assertThat(updatedStatus.getDescription()).isEqualTo(crudsr.getDescription());
        assertThat(updatedStatus.getDossierCount()).isNull();
        assertThat(updatedStatus.getRank()).isEqualTo(crudsr.getRank());

        // get all for template id
        allDossierStatus = dossierStatusClient.getAllDossierStatusForTemplate(dossierTemplate.getId());
        assertThat(allDossierStatus.size()).isEqualTo(1);
        assertThat(allDossierStatus.get(0).getDossierCount()).isZero();

        var testDossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "1", allDossierStatus.iterator().next());

        assertThat(testDossier.getDossierStatusId()).isEqualTo(allDossierStatus.iterator().next().getId());

        updatedStatus = dossierStatusClient.getDossierStatus(loadedDossierStatus.getId());
        assertThat(updatedStatus.getDossierCount()).isEqualTo(1);

        allDossierStatus = dossierStatusClient.getAllDossierStatusForTemplate(dossierTemplate.getId());
        assertThat(allDossierStatus.size()).isEqualTo(1);

        assertThat(allDossierStatus.iterator().next().getDossierCount()).isEqualTo(1);

        // update dossier with dossier status null
        var cru = new DossierRequest();
        BeanUtils.copyProperties(testDossier, cru);
        cru.setDossierTemplateId(testDossier.getDossierTemplateId());
        cru.setDossierStatusId(null);
        var updated = dossierClient.createDossierOrUpdateDossier(cru).getBody();
        assertThat(updated.getDossierStatusId()).isNull();

        updatedStatus = dossierStatusClient.getDossierStatus(loadedDossierStatus.getId());
        assertThat(updatedStatus.getDossierCount()).isZero();

        // Create
        var crudsr2 = new DossierStatusRequest();
        crudsr2.setName("name3");
        crudsr2.setDescription("description3");
        crudsr2.setRank(1);
        crudsr2.setColor("#cccccc");
        crudsr2.setDossierTemplateId(dossierTemplate.getId());

        // create second dossier status
        var loadedDossierStatus2 = dossierStatusClient.createOrUpdateDossierStatus(crudsr2);
        assertThat(loadedDossierStatus2).isNotNull();
        assertThat(loadedDossierStatus2.getRank()).isEqualTo(crudsr2.getRank());
        loadedDossierStatus = dossierStatusClient.getDossierStatus(loadedDossierStatus.getId());
        assertThat(loadedDossierStatus.getRank()).isEqualTo(crudsr.getRank() + 1);
        allDossierStatus = dossierStatusClient.getAllDossierStatusForTemplate(dossierTemplate.getId());
        assertThat(allDossierStatus.size()).isEqualTo(2);

        //delete first status with itself
        try {
            dossierStatusClient.deleteDossierStatus(loadedDossierStatus.getId(), loadedDossierStatus.getId());
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(400);
        }
        //delete with unknown status
        try {
            dossierStatusClient.deleteDossierStatus(loadedDossierStatus.getId(), "unknown");
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(404);
        }

        // update dossier with dossier status
        var cru2 = new DossierRequest();
        BeanUtils.copyProperties(testDossier, cru2);
        cru2.setDossierTemplateId(testDossier.getDossierTemplateId());
        cru2.setDossierStatusId(loadedDossierStatus.getId());
        updated = dossierClient.createDossierOrUpdateDossier(cru2).getBody();
        assertThat(updated.getDossierStatusId()).isNotNull();
        //delete and replace
        dossierStatusClient.deleteDossierStatus(loadedDossierStatus.getId(), loadedDossierStatus2.getId());
        allDossierStatus = dossierStatusClient.getAllDossierStatusForTemplate(dossierTemplate.getId());
        assertThat(allDossierStatus.size()).isEqualTo(1);
        assertThat(allDossierStatus.get(0).getDossierCount()).isEqualTo(1);
        // check dossier has the new dossier status
        updated = dossierClient.getDossier(updated.getId(), false, false);
        assertThat(updated.getDossierStatusId()).isEqualTo(loadedDossierStatus2.getId());
    }

}
