package kr.itn.itnhub.shared;

import kr.itn.itnhub.config.CurrentUser;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.List;
import java.util.Map;

/** 자료실. 기관에 딸리지 않는 공용 서식을 올려두고 내려받는다(요구사항 [26]). */
@RestController
public class SharedFileController {

    private final SharedFileService service;
    private final CurrentUser currentUser;

    public SharedFileController(SharedFileService service, CurrentUser currentUser) {
        this.service = service;
        this.currentUser = currentUser;
    }

    @GetMapping("/api/shared-files")
    public List<SharedFile> list() {
        return service.list();
    }

    @PostMapping("/api/shared-files")
    public List<SharedFile> add(@RequestPart("file") MultipartFile file,
                                @RequestPart(value = "description", required = false) String description,
                                Principal principal) throws IOException {
        String name = file.getOriginalFilename() == null ? "file" : file.getOriginalFilename();
        return service.add(name, description, file.getContentType(), file.getBytes(),
                currentUser.displayName(principal));
    }

    @PutMapping("/api/shared-files/{id}")
    public List<SharedFile> updateDescription(@PathVariable Long id,
                                              @RequestBody Map<String, String> body) {
        return service.updateDescription(id, body.get("description"));
    }

    /** 한글 파일명이 깨지지 않게 보고서 다운로드와 같은 RFC 5987 인코딩을 쓴다. */
    @GetMapping("/api/shared-files/{id}")
    public ResponseEntity<byte[]> download(@PathVariable Long id) {
        SharedFileMapper.Content found = service.content(id);
        String encodedName = URLEncoder.encode(found.fileName(), StandardCharsets.UTF_8)
                .replace("+", "%20");
        MediaType type = found.contentType() == null || found.contentType().isBlank()
                ? MediaType.APPLICATION_OCTET_STREAM
                : MediaType.parseMediaType(found.contentType());

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName)
                .contentType(type)
                .body(found.content());
    }

    @ResponseStatus(HttpStatus.NO_CONTENT)
    @DeleteMapping("/api/shared-files/{id}")
    public void delete(@PathVariable Long id) {
        service.delete(id);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(IllegalArgumentException.class)
    public Map<String, String> handleBadRequest(IllegalArgumentException e) {
        return Map.of("message", e.getMessage());
    }
}
