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.file.ActionResponse;
import ru.soune.nocopy.dto.file.FileEntityRequest;
import ru.soune.nocopy.dto.file.FileEntityResponse;
import ru.soune.nocopy.dto.file.ModerationActionRequest;
import ru.soune.nocopy.entity.file.FileStatus;
import ru.soune.nocopy.exception.FileEntityNotFoundException;
import ru.soune.nocopy.service.file.FileEntityService;
import ru.soune.nocopy.service.file.moderation.ModerationService;

import java.util.Arrays;
import java.util.Map;

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

    private final ObjectMapper objectMapper;

    private final ModerationService moderationService;

    private final FileEntityService fileEntityService;

    @Override
    public BaseResponse handle(BaseRequest request) throws Exception {
        try {
            FileEntityRequest fileRequest = objectMapper.convertValue(request.getMessageBody(), FileEntityRequest.class);

            String action = fileRequest.getAction();
            switch (action) {
                case "moderate_file":
                    return handleModerateFile(request, fileRequest);
                case "review_appeal":
                    return handleReviewAppeal(request, fileRequest);
                case "change_file_status":
                    return handleChangeStatus(request, fileRequest);
                default:
                    ActionResponse response = ActionResponse.builder()
                            .action(action)
                            .availableActions(Arrays.asList(
                                    "moderate_file", "change_file_status", "review_appeal"))
                            .build();

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

            }
        } catch (Exception e) {
            log.error("Error in FileEntityHandler", e);
            return new BaseResponse(request.getMsgId(),
                    MessageCode.FILE_UPLOAD_ERROR.getCode(),
                    "Handler error: " + e.getMessage(),
                    null);
        }
    }

    private BaseResponse handleChangeStatus(BaseRequest request, FileEntityRequest fileRequest) {
        FileStatus newStatus = fileRequest.getFileStatus();
        String fileId = fileRequest.getFileId();

        try {
            fileEntityService.changeFileStatus(newStatus ,fileRequest.getFileId());
        } catch (FileEntityNotFoundException e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.FILE_NOT_FOUND.getCode(),
                    MessageCode.FILE_NOT_FOUND.getDescription(),
                    FileEntityResponse.builder().id(fileId).build());
        }

        return new BaseResponse(request.getMsgId(),
                MessageCode.SUCCESS.getCode(),
                MessageCode.SUCCESS.getDescription(),
                Map.of("file_status", newStatus, "file_id", fileId));
    }

    private BaseResponse handleReviewAppeal(BaseRequest request, FileEntityRequest fileRequest) {
        try {
            String appealId = fileRequest.getAppealId();
            Boolean approve = fileRequest.getApprove();
            String comment = fileRequest.getComment() == null ? "": fileRequest.getComment();

            if (appealId == null || approve == null) {
                return new BaseResponse(request.getMsgId(),
                        MessageCode.INVALID_FIELD.getCode(),
                        "appealId and approve are required",
                        null);
            }

            moderationService.reviewAppeal(appealId, approve, comment, request.getAdminId());

            return new BaseResponse(request.getMsgId(),
                    MessageCode.SUCCESS.getCode(),
                    "Appeal reviewed successfully",
                    Map.of(
                            "appealId", appealId,
                            "approved", approve,
                            "comment", comment
                    ));

        } catch (SecurityException e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.ACCESS_DENIED.getCode(),
                    "Admin access required", null);
        } catch (IllegalStateException e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.INVALID_FIELD.getCode(),
                    e.getMessage(),
                    null);
        } catch (Exception e) {
            log.error("Error reviewing appeal", e);
            return new BaseResponse(request.getMsgId(),
                    MessageCode.INVALID_FIELD.getCode(),
                    "Failed to review appeal: " + e.getMessage(),
                    null);
        }
    }

    private BaseResponse handleModerateFile(BaseRequest request, FileEntityRequest fileRequest) {
        try {
            ModerationActionRequest moderationRequest = ModerationActionRequest.builder()
                    .fileId(fileRequest.getFileId())
                    .newStatus(fileRequest.getFileStatus())
                    .comment(fileRequest.getComment())
                    .build();

            moderationService.moderateFile(moderationRequest, request.getAdminId());

            return new BaseResponse(request.getMsgId(),
                    MessageCode.SUCCESS_MODERATION.getCode(),
                    MessageCode.SUCCESS_MODERATION.getDescription(),
                    Map.of("file_id", fileRequest.getFileId()));
        } catch (SecurityException e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.ACCESS_DENIED.getCode(),
                    MessageCode.ACCESS_DENIED.getDescription(),
                    Map.of("file_id", fileRequest.getFileId()));
        } catch (FileEntityNotFoundException e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.FILE_NOT_FOUND.getCode(),
                    MessageCode.FILE_NOT_FOUND.getDescription(),
                    Map.of("file_id", fileRequest.getFileId()));
        } catch (IllegalStateException e) {
            return new BaseResponse(request.getMsgId(),
                    MessageCode.ILLEGAL_STATE.getCode(),
                    MessageCode.ILLEGAL_STATE.getDescription(),
                    Map.of("file_id", fileRequest.getFileId()));
        }
    }
}
