package org.raddatz.familienarchiv.document.transcription;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.raddatz.familienarchiv.document.transcription.CreateTranscriptionBlockDTO;
import org.raddatz.familienarchiv.document.transcription.ReorderTranscriptionBlocksDTO;
import org.raddatz.familienarchiv.document.transcription.UpdateTranscriptionBlockDTO;
import org.raddatz.familienarchiv.document.transcription.TranscriptionBlock;
import org.raddatz.familienarchiv.document.transcription.TranscriptionBlockVersion;
import org.raddatz.familienarchiv.security.Permission;
import org.raddatz.familienarchiv.security.RequirePermission;
import org.raddatz.familienarchiv.security.SecurityUtils;
import org.raddatz.familienarchiv.document.transcription.TranscriptionService;
import org.raddatz.familienarchiv.user.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/api/documents/{documentId}/transcription-blocks")
@RequiredArgsConstructor
@Slf4j
public class TranscriptionBlockController {

    private final TranscriptionService transcriptionService;
    private final UserService userService;

    @GetMapping
    @RequirePermission(Permission.READ_ALL)
    public List<TranscriptionBlock> listBlocks(@PathVariable UUID documentId) {
        return transcriptionService.listBlocks(documentId);
    }

    @GetMapping("/{blockId}")
    @RequirePermission(Permission.READ_ALL)
    public TranscriptionBlock getBlock(@PathVariable UUID documentId, @PathVariable UUID blockId) {
        return transcriptionService.getBlock(documentId, blockId);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    @RequirePermission({Permission.ANNOTATE_ALL, Permission.WRITE_ALL})
    public TranscriptionBlock createBlock(
            @PathVariable UUID documentId,
            @Valid @RequestBody CreateTranscriptionBlockDTO dto,
            Authentication authentication) {
        UUID userId = requireUserId(authentication);
        return transcriptionService.createBlock(documentId, dto, userId);
    }

    @PutMapping("/{blockId}")
    @RequirePermission({Permission.ANNOTATE_ALL, Permission.WRITE_ALL})
    public TranscriptionBlock updateBlock(
            @PathVariable UUID documentId,
            @PathVariable UUID blockId,
            @Valid @RequestBody UpdateTranscriptionBlockDTO dto,
            Authentication authentication) {
        UUID userId = requireUserId(authentication);
        return transcriptionService.updateBlock(documentId, blockId, dto, userId);
    }

    @DeleteMapping("/{blockId}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @RequirePermission({Permission.ANNOTATE_ALL, Permission.WRITE_ALL})
    public void deleteBlock(
            @PathVariable UUID documentId,
            @PathVariable UUID blockId) {
        transcriptionService.deleteBlock(documentId, blockId);
    }

    @PutMapping("/reorder")
    @RequirePermission({Permission.ANNOTATE_ALL, Permission.WRITE_ALL})
    public List<TranscriptionBlock> reorderBlocks(
            @PathVariable UUID documentId,
            @RequestBody ReorderTranscriptionBlocksDTO dto) {
        transcriptionService.reorderBlocks(documentId, dto);
        return transcriptionService.listBlocks(documentId);
    }

    @PutMapping("/{blockId}/review")
    @RequirePermission({Permission.ANNOTATE_ALL, Permission.WRITE_ALL})
    public TranscriptionBlock reviewBlock(
            @PathVariable UUID documentId,
            @PathVariable UUID blockId,
            Authentication authentication) {
        UUID userId = requireUserId(authentication);
        return transcriptionService.reviewBlock(documentId, blockId, userId);
    }

    @PutMapping("/review-all")
    @RequirePermission({Permission.ANNOTATE_ALL, Permission.WRITE_ALL})
    public List<TranscriptionBlock> markAllBlocksReviewed(
            @PathVariable UUID documentId,
            Authentication authentication) {
        UUID userId = requireUserId(authentication);
        return transcriptionService.markAllBlocksReviewed(documentId, userId);
    }

    @GetMapping("/{blockId}/history")
    @RequirePermission(Permission.READ_ALL)
    public List<TranscriptionBlockVersion> getBlockHistory(
            @PathVariable UUID documentId,
            @PathVariable UUID blockId) {
        return transcriptionService.getBlockHistory(documentId, blockId);
    }

    private UUID requireUserId(Authentication authentication) {
        return SecurityUtils.requireUserId(authentication, userService);
    }
}
