package cn.novalon.gym.manage.file.handler;

import cn.novalon.gym.manage.file.core.domain.SysFile;
import cn.novalon.gym.manage.file.core.service.ISysFileService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class SysFileHandlerTest {

    @Mock
    private ISysFileService fileService;

    private SysFileHandler fileHandler;

    private SysFile testFile;

    @BeforeEach
    void setUp() {
        fileHandler = new SysFileHandler(fileService);
        testFile = new SysFile();
        testFile.setId(1L);
        testFile.setFileName("test.txt");
        testFile.setFilePath("/tmp/uploads/test.txt");
        testFile.setFileType("text/plain");
        testFile.setFileSize(1024L);
        testFile.setCreateBy("testuser");
    }

    @Test
    void testGetAllFiles_Success() {
        when(fileService.getAllFiles()).thenReturn(Flux.just(testFile));
        
        ServerRequest request = MockServerRequest.builder().build();
        Mono<ServerResponse> response = fileHandler.getAllFiles(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
        
        verify(fileService).getAllFiles();
    }

    @Test
    void testGetFileById_Success() {
        when(fileService.getFileById(1L)).thenReturn(Mono.just(testFile));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .build();
        Mono<ServerResponse> response = fileHandler.getFileById(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.OK)
                .verifyComplete();
        
        verify(fileService).getFileById(1L);
    }

    @Test
    void testGetFileById_NotFound() {
        when(fileService.getFileById(999L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "999")
                .build();
        Mono<ServerResponse> response = fileHandler.getFileById(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getFileById(999L);
    }

    @Test
    void testDeleteFile_Success() {
        when(fileService.deleteFile(1L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .build();
        Mono<ServerResponse> response = fileHandler.deleteFile(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NO_CONTENT)
                .verifyComplete();
        
        verify(fileService).deleteFile(1L);
    }

    @Test
    void testDeleteFile_NotFound() {
        when(fileService.deleteFile(999L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "999")
                .build();
        Mono<ServerResponse> response = fileHandler.deleteFile(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NO_CONTENT)
                .verifyComplete();
        
        verify(fileService).deleteFile(999L);
    }

    @Test
    void testDownloadFile_Success() {
        when(fileService.getFileById(1L)).thenReturn(Mono.just(testFile));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .build();
        Mono<ServerResponse> response = fileHandler.downloadFile(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getFileById(1L);
    }

    @Test
    void testDownloadFile_NotFound() {
        when(fileService.getFileById(999L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "999")
                .build();
        Mono<ServerResponse> response = fileHandler.downloadFile(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getFileById(999L);
    }

    @Test
    void testDownloadFileByName_Success() {
        when(fileService.getAllFiles()).thenReturn(Flux.just(testFile));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("fileName", "test.txt")
                .build();
        Mono<ServerResponse> response = fileHandler.downloadFileByName(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getAllFiles();
    }

    @Test
    void testDownloadFileByName_NotFound() {
        when(fileService.getAllFiles()).thenReturn(Flux.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("fileName", "nonexistent.txt")
                .build();
        Mono<ServerResponse> response = fileHandler.downloadFileByName(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getAllFiles();
    }

    @Test
    void testPreviewFile_Success() {
        when(fileService.getFileById(1L)).thenReturn(Mono.just(testFile));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "1")
                .build();
        Mono<ServerResponse> response = fileHandler.previewFile(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getFileById(1L);
    }

    @Test
    void testPreviewFile_NotFound() {
        when(fileService.getFileById(999L)).thenReturn(Mono.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("id", "999")
                .build();
        Mono<ServerResponse> response = fileHandler.previewFile(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getFileById(999L);
    }

    @Test
    void testPreviewFileByName_Success() {
        when(fileService.getAllFiles()).thenReturn(Flux.just(testFile));
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("fileName", "test.txt")
                .build();
        Mono<ServerResponse> response = fileHandler.previewFileByName(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getAllFiles();
    }

    @Test
    void testPreviewFileByName_NotFound() {
        when(fileService.getAllFiles()).thenReturn(Flux.empty());
        
        ServerRequest request = MockServerRequest.builder()
                .pathVariable("fileName", "nonexistent.txt")
                .build();
        Mono<ServerResponse> response = fileHandler.previewFileByName(request);
        
        StepVerifier.create(response)
                .expectNextMatches(serverResponse -> 
                    serverResponse.statusCode() == HttpStatus.NOT_FOUND)
                .verifyComplete();
        
        verify(fileService).getAllFiles();
    }
}
