package ru.soune.nocopy.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.docviewer.DocViewerRequest;
import ru.soune.nocopy.dto.docviewer.DockViewStatsResponse;
import ru.soune.nocopy.dto.file.ActionResponse;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.exception.NotFoundAuthToken;
import ru.soune.nocopy.service.dockview.DockViewService;
import ru.soune.nocopy.service.file.FileEntityService;
import ru.soune.nocopy.service.register.AuthService;

import java.util.Arrays;
import java.util.List;

@Component
@RequiredArgsConstructor
@Slf4j
public class DockViewFileHandler implements RequestHandler {

    private final DockViewService dockViewService;

    private final FileEntityService fileEntityService;

    private final AuthService authService;

    private final ObjectMapper objectMapper;

    @Override
    public BaseResponse handle(BaseRequest request) throws Exception {
        DocViewerRequest docViewerRequest = objectMapper.convertValue(request.getMessageBody(), DocViewerRequest.class);
        String action = docViewerRequest.getAction();

        switch (action) {
            case "history_view":
                return handleGetHistory(request, docViewerRequest);
            case "view_stats":
                return handleGetViewStats(request, docViewerRequest);
            default:
                ActionResponse response = ActionResponse.builder()
                        .action(action)
                        .availableActions(Arrays.asList("history_view", "view_stats"))
                        .build();

                return new BaseResponse(request.getMsgId(), MessageCode.INVALID_ACTION.getCode(),
                        "Invalid action: " + action, response);
        }
    }

    private BaseResponse handleGetHistory(BaseRequest request, DocViewerRequest docViewerRequest) {
        try {
            Long userId =  authService.useUserAuthToken(docViewerRequest.getToken());
            List<String> fileIds = fileEntityService.getAllUserFiles(userId)
                    .stream()
                    .filter(fileEntity -> fileEntity.getMimeType().equals("document"))
                    .map(FileEntity::getId)
                    .toList();

            if (fileIds.isEmpty()) {
                return new BaseResponse(request.getMsgId(),
                        MessageCode.FILE_NOT_FOUND.getCode(),
                        "Files for search not found",
                        null);
            }

            DockViewStatsResponse openLastHistory = dockViewService.getOpenLastHistory(docViewerRequest.getPage(),
                    docViewerRequest.getSize(), docViewerRequest.getSortDirection(), docViewerRequest.getSortBy(),
                    fileIds);

            return new BaseResponse(request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    MessageCode.SUCCESS.getDescription(),
                    openLastHistory);

        } catch (NotFoundAuthToken e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.INVALID_TOKEN.getCode(),
                    "Authentication required",
                    null);
        } catch (Exception e) {
            log.error("Error getting view history", e);
            return new BaseResponse(request.getMsgId(),
                    MessageCode.FILE_NOT_FOUND.getCode(),
                    "Failed to get file view history: " + e.getMessage(),
                    null);
        }
    }

    private BaseResponse handleGetViewStats(BaseRequest request, DocViewerRequest docViewerRequest) {
        try {
            Long userId = authService.useUserAuthToken(docViewerRequest.getToken());
            List<String> fileIds = fileEntityService.getAllUserFiles(userId)
                    .stream()
                    .filter(fileEntity -> fileEntity.getMimeType().equals("document"))
                    .map(FileEntity::getId)
                    .toList();

            if (fileIds.isEmpty()) {
                return new BaseResponse(request.getMsgId(),
                        MessageCode.FILE_NOT_FOUND.getCode(),
                        "Files for search not found",
                        null);
            }

            DockViewStatsResponse totalStats = dockViewService.getTotalStatsByFileIds(fileIds);

            return new BaseResponse(request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    MessageCode.SUCCESS.getDescription(),
                    totalStats);
        } catch (NotFoundAuthToken e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.INVALID_TOKEN.getCode(),
                    "Authentication required",
                    null);
        }
    }
}
