package com.zhengmeng.ocrplatform.recognition;

import com.zhengmeng.ocrplatform.common.ApiResponse;
import com.zhengmeng.ocrplatform.common.PageResponse;
import com.zhengmeng.ocrplatform.integration.PluginIntegrationInterceptor;
import com.zhengmeng.ocrplatform.task.OcrTaskService;
import com.zhengmeng.ocrplatform.task.TaskNotFoundException;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/v1/ocr/tasks/{taskId}")
public class OcrRecognitionController {
    private final OcrTaskService taskService;
    private final OcrRawResultRepository rawResultRepository;
    private final OcrTextBlockRepository textBlockRepository;

    public OcrRecognitionController(OcrTaskService taskService,
                                    OcrRawResultRepository rawResultRepository,
                                    OcrTextBlockRepository textBlockRepository) {
        this.taskService = taskService;
        this.rawResultRepository = rawResultRepository;
        this.textBlockRepository = textBlockRepository;
    }

    @GetMapping("/raw-results")
    public ApiResponse<List<OcrRawResultSummaryItem>> listRawResults(@PathVariable String taskId, HttpServletRequest request) {
        ensureResultReadable(taskId, request);
        return ApiResponse.ok(rawResultRepository.findByTaskIdOrderByRunNoAscIdAsc(taskId).stream()
                .map(OcrRawResultSummaryItem::from)
                .toList());
    }

    @GetMapping("/raw-results/{rawResultId}")
    public ApiResponse<OcrRawResultItem> getRawResult(@PathVariable String taskId, @PathVariable Long rawResultId, HttpServletRequest request) {
        ensureResultReadable(taskId, request);
        return ApiResponse.ok(rawResultRepository.findByIdAndTaskId(rawResultId, taskId)
                .map(OcrRawResultItem::from)
                .orElseThrow(() -> new TaskNotFoundException(taskId + "/raw-results/" + rawResultId)));
    }

    @GetMapping("/text-blocks")
    public ApiResponse<PageResponse<OcrTextBlockSummaryItem>> listTextBlocks(@PathVariable String taskId,
                                                                             @RequestParam(defaultValue = "0") int page,
                                                                             @RequestParam(defaultValue = "100") int size,
                                                                             HttpServletRequest request) {
        ensureResultReadable(taskId, request);
        int safePage = Math.max(page, 0);
        int safeSize = Math.min(Math.max(size, 1), 500);
        Pageable pageable = PageRequest.of(safePage, safeSize);
        return ApiResponse.ok(PageResponse.from(textBlockRepository
                .findByTaskIdOrderByRunNoAscPageNoAscReadingOrderAscIdAsc(taskId, pageable)
                .map(OcrTextBlockSummaryItem::from)));
    }

    private void ensureTaskExists(String taskId, HttpServletRequest request) {
        taskService.findTask(taskId, clientCode(request)).orElseThrow(() -> new TaskNotFoundException(taskId));
    }

    private void ensureResultReadable(String taskId, HttpServletRequest request) {
        taskService.ensureResultReadable(taskId, clientCode(request));
    }

    private String clientCode(HttpServletRequest request) {
        Object value = request.getAttribute(PluginIntegrationInterceptor.REQUEST_CLIENT_CODE);
        return value instanceof String clientCode ? clientCode : null;
    }
}
