package com.ga.api.controller.attachment;

import com.ga.api.service.attachment.AttachmentService;
import com.ga.common.annotation.DataChangeLog;
import com.ga.common.annotation.RequirePermission;
import com.ga.common.model.ApiResponse;
import com.ga.common.model.PageResponse;
import com.ga.core.vo.attachment.AttachmentResp;
import com.ga.core.vo.attachment.AttachmentSearchParam;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

@Tag(name = "첨부파일")
@RestController
@RequestMapping("/api/attachments")
@RequiredArgsConstructor
public class AttachmentController {

    private final AttachmentService service;

    @GetMapping
    @RequirePermission(menu = "ATTACHMENT", perm = "READ")
    public ApiResponse<PageResponse<AttachmentResp>> list(@ModelAttribute AttachmentSearchParam param) {
        return ApiResponse.ok(service.list(param));
    }

    @GetMapping("/by-ref")
    @RequirePermission(menu = "ATTACHMENT", perm = "READ")
    public ApiResponse<List<AttachmentResp>> listByRef(@RequestParam String refType,
                                                       @RequestParam Long refId) {
        return ApiResponse.ok(service.listByRef(refType, refId));
    }

    @GetMapping("/{attachmentId}/meta")
    @RequirePermission(menu = "ATTACHMENT", perm = "READ")
    public ApiResponse<AttachmentResp> detail(@PathVariable Long attachmentId) {
        return ApiResponse.ok(service.detail(attachmentId));
    }

    @PostMapping(consumes = "multipart/form-data")
    @RequirePermission(menu = "ATTACHMENT", perm = "CREATE")
    @DataChangeLog(menu = "ATTACHMENT", table = "attachment")
    public ApiResponse<Long> upload(@RequestParam("file") MultipartFile file,
                                    @RequestParam String refType,
                                    @RequestParam Long refId) {
        return ApiResponse.ok(service.upload(file, refType, refId));
    }

    @GetMapping("/{attachmentId}/download")
    @RequirePermission(menu = "ATTACHMENT", perm = "READ")
    public void download(@PathVariable Long attachmentId, HttpServletResponse response) throws IOException {
        AttachmentResp meta = service.detail(attachmentId);
        Path filePath = service.resolveFilePath(attachmentId);

        response.setContentType(meta.getMimeType() != null ? meta.getMimeType() : MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);
        String encodedName = URLEncoder.encode(meta.getFileName(), StandardCharsets.UTF_8).replace("+", "%20");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName);
        response.setContentLengthLong(meta.getFileSize() != null ? meta.getFileSize() : 0L);

        try (OutputStream out = response.getOutputStream()) {
            Files.copy(filePath, out);
        }
    }

    @DeleteMapping("/{attachmentId}")
    @RequirePermission(menu = "ATTACHMENT", perm = "DELETE")
    @DataChangeLog(menu = "ATTACHMENT", table = "attachment")
    public ApiResponse<Void> delete(@PathVariable Long attachmentId) {
        service.delete(attachmentId);
        return ApiResponse.ok();
    }
}
