package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.api.dto.document.request.CreateDocumentRequest;
import dev.lions.unionflow.server.api.dto.document.request.CreatePieceJointeRequest;
import dev.lions.unionflow.server.api.dto.document.response.DocumentResponse;
import dev.lions.unionflow.server.api.dto.document.response.PieceJointeResponse;
import dev.lions.unionflow.server.entity.Document;
import dev.lions.unionflow.server.entity.PieceJointe;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;

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

/**
 * Tests de couverture complémentaires pour DocumentService.
 * Couvre les branches défensives manquées dans les méthodes privées :
 *  - convertToResponse(Document null) → null
 *  - convertToEntity(CreateDocumentRequest null) → null
 *  - convertToResponse(PieceJointe null) → null
 *  - convertToResponse(PieceJointe) avec document == null → documentId non affecté
 *  - convertToEntity(CreatePieceJointeRequest null) → null
 */
@QuarkusTest
class DocumentServiceCoverageTest {

    @Inject
    DocumentService documentService;

    private Method getConvertToResponseDocument() throws Exception {
        Method m = DocumentService.class.getDeclaredMethod("convertToResponse", Document.class);
        m.setAccessible(true);
        return m;
    }

    private Method getConvertToResponsePieceJointe() throws Exception {
        Method m = DocumentService.class.getDeclaredMethod("convertToResponse", PieceJointe.class);
        m.setAccessible(true);
        return m;
    }

    private Method getConvertToEntityDocument() throws Exception {
        Method m = DocumentService.class.getDeclaredMethod("convertToEntity", CreateDocumentRequest.class);
        m.setAccessible(true);
        return m;
    }

    private Method getConvertToEntityPieceJointe() throws Exception {
        Method m = DocumentService.class.getDeclaredMethod("convertToEntity", CreatePieceJointeRequest.class);
        m.setAccessible(true);
        return m;
    }

    @Test
    @DisplayName("convertToResponse(Document null) retourne null (branche défensive)")
    void convertToResponseDocument_null_returnsNull() throws Exception {
        Object result = getConvertToResponseDocument().invoke(documentService, (Object) null);
        assertThat(result).isNull();
    }

    @Test
    @DisplayName("convertToEntity(CreateDocumentRequest null) retourne null (branche défensive)")
    void convertToEntityDocument_null_returnsNull() throws Exception {
        Object result = getConvertToEntityDocument().invoke(documentService, (Object) null);
        assertThat(result).isNull();
    }

    @Test
    @DisplayName("convertToResponse(PieceJointe null) retourne null (branche défensive)")
    void convertToResponsePieceJointe_null_returnsNull() throws Exception {
        Object result = getConvertToResponsePieceJointe().invoke(documentService, (Object) null);
        assertThat(result).isNull();
    }

    @Test
    @DisplayName("convertToResponse(PieceJointe) avec document null ne met pas documentId (branche false)")
    void convertToResponsePieceJointe_documentNull_doesNotSetDocumentId() throws Exception {
        // PieceJointe sans document (document == null) → branche false de if (pj.getDocument() != null)
        PieceJointe pj = new PieceJointe();
        pj.setOrdre(1);
        pj.setLibelle("PJ sans document");
        // document est null par défaut

        PieceJointeResponse response = (PieceJointeResponse) getConvertToResponsePieceJointe()
                .invoke(documentService, pj);

        assertThat(response).isNotNull();
        assertThat(response.getLibelle()).isEqualTo("PJ sans document");
        assertThat(response.getDocumentId()).isNull(); // documentId non affecté car document == null
    }

    @Test
    @DisplayName("convertToEntity(CreatePieceJointeRequest null) retourne null (branche défensive)")
    void convertToEntityPieceJointe_null_returnsNull() throws Exception {
        Object result = getConvertToEntityPieceJointe().invoke(documentService, (Object) null);
        assertThat(result).isNull();
    }

    @Test
    @DisplayName("convertToEntity(CreateDocumentRequest) avec typeDocument null → TypeDocument.AUTRE (branche ternaire L179)")
    void convertToEntityDocument_typeDocumentNull_defaultsToAUTRE() throws Exception {
        // Crée une requête avec typeDocument == null → branche false du ternaire :
        // dto.typeDocument() != null ? dto.typeDocument() : TypeDocument.AUTRE → AUTRE
        CreateDocumentRequest request = CreateDocumentRequest.builder()
                .nomFichier("document-test.pdf")
                .nomOriginal("original.pdf")
                .typeDocument(null) // null → typeDocument défaut = TypeDocument.AUTRE
                .build();

        Object result = getConvertToEntityDocument().invoke(documentService, request);

        assertThat(result).isNotNull();
        Document document = (Document) result;
        assertThat(document.getTypeDocument())
                .isEqualTo(dev.lions.unionflow.server.api.enums.document.TypeDocument.AUTRE);
    }
}
