package ru.soune.nocopy.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import ru.soune.nocopy.dto.file.CheckStatus;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.entity.file.ProtectionStatus;
import ru.soune.nocopy.entity.user.ProtectedFileCheck;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.file.CheckCounterService;
import ru.soune.nocopy.service.file.FileStorageService;
import org.springframework.http.ContentDisposition;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import java.io.IOException;

@RestController
@RequestMapping("/api/files")
@Slf4j
public class FileController {

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private FileEntityRepository fileRepository;

    @Autowired
    private CheckCounterService checkCounterService;

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/public/{fileId}")
    public ResponseEntity<Resource> getPublicFile(
            @PathVariable String fileId) throws IOException {

        FileEntity fileEntity = fileRepository.findById(fileId)
                .orElseThrow(() -> new RuntimeException("File not found"));

        Resource resource = fileStorageService.loadFileAsResource(fileEntity.getFilePath());

        ContentDisposition contentDisposition = ContentDisposition.inline()
                .filename(fileEntity.getOriginalFileName(), StandardCharsets.UTF_8)
                .build();

        return ResponseEntity.ok()
                .contentType(new MediaType(fileEntity.getMimeType(), fileEntity.getFileExtension()))
                .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
                .body(resource);
    }

    @GetMapping("/protected/{fileId}")
    public ResponseEntity<Resource> getProtectedFile(
            @PathVariable String fileId) throws IOException {

        FileEntity fileEntity = fileRepository.findById(fileId)
                .orElseThrow(() -> new RuntimeException("File not found"));

        Resource resource = fileStorageService.loadFileAsResource(fileEntity.getProtectedFilePath());

        if (fileEntity.getProtectionStatus() == ProtectionStatus.NOT_PROTECTED ||
                fileEntity.getProtectionStatus() == ProtectionStatus.PROCESSING) {
            throw new RuntimeException("File is not protected");
        }

        String fileName = fileEntity.getOriginalFileName().replace("." +
                fileEntity.getFileExtension(), "") + "_nocopy_protected" +
                "." + fileEntity.getFileExtension();
        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
                .replace("+", "%20");

        return ResponseEntity.ok()
                .contentType(new MediaType(fileEntity.getMimeType(), fileEntity.getFileExtension()))
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "inline; filename*=UTF-8''" + encodedFileName)
                .body(resource);
    }

    @GetMapping("check-file/status/{userId}")
    public ResponseEntity<CheckStatus> getStatus(@PathVariable Long userId) {
        CheckStatus status = checkCounterService.getCurrentStatus(userId);

        return ResponseEntity.ok(status);
    }

    @PostMapping("check-file/update-limit/{userId}/{limit}")
    public ResponseEntity<ProtectedFileCheck> getStatus(@PathVariable Long userId, @PathVariable Integer limit) {
        User user = userRepository.findById(userId).orElseThrow();
        ProtectedFileCheck protectedFileCheck = checkCounterService.updateLimit(user, limit);

        return ResponseEntity
                .ok()
                .body(protectedFileCheck);
    }
}
