package kr.itn.itnhub.process;

import kr.itn.itnhub.org.OrgNotFoundException;
import kr.itn.itnhub.org.Organization;
import kr.itn.itnhub.org.OrganizationMapper;
import kr.itn.itnhub.seed.SeedParseException;
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.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.RequestParam;
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.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/** 기관관리 상세의 권리처리 탭이 부르는 엔드포인트. */
@RestController
public class ProcessController {

    private final ProcessService processService;
    private final ProcessImportService importService;
    private final OrganizationMapper orgMapper;

    public ProcessController(ProcessService processService, ProcessImportService importService,
                              OrganizationMapper orgMapper) {
        this.processService = processService;
        this.importService = importService;
        this.orgMapper = orgMapper;
    }

    @PostMapping("/api/orgs/{id}/process/import")
    public ProcessImportReport upload(@PathVariable("id") Long orgId, @RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            throw new SeedParseException("업로드된 파일이 비어 있습니다.");
        }
        String filename = file.getOriginalFilename();
        if (filename == null || !hasAllowedExtension(filename)) {
            throw new SeedParseException("엑셀 파일(.xlsx 또는 .xlsm)만 업로드할 수 있습니다.");
        }
        try (InputStream in = file.getInputStream()) {
            return importService.importFile(orgId, in);
        } catch (IOException e) {
            throw new SeedParseException("엑셀 파일을 읽지 못했습니다.", e);
        }
    }

    @GetMapping("/api/orgs/{id}/process")
    public ProcessPage list(@PathVariable("id") Long orgId,
                             @RequestParam(required = false) String keyword,
                             @RequestParam(required = false) String status,
                             @RequestParam(defaultValue = "0") int page,
                             @RequestParam(defaultValue = "30") int size) {
        return processService.list(orgId, keyword, status, page, size);
    }

    @GetMapping("/api/orgs/{id}/process/{itemId}")
    public ProcessItem get(@PathVariable("id") Long orgId, @PathVariable Long itemId) {
        return processService.get(orgId, itemId);
    }

    @PutMapping("/api/orgs/{id}/process/{itemId}")
    public ProcessItem update(@PathVariable("id") Long orgId, @PathVariable Long itemId,
                               @RequestBody ProcessingRequest request) {
        return processService.updateProcessing(orgId, itemId, request);
    }

    @ResponseStatus(HttpStatus.NO_CONTENT)
    @DeleteMapping("/api/orgs/{id}/process/{itemId}")
    public void delete(@PathVariable("id") Long orgId, @PathVariable Long itemId) {
        processService.delete(orgId, itemId);
    }

    /** 한글 파일명이라 ReviewController.download와 동일하게 RFC 5987 인코딩을 쓴다. */
    @GetMapping("/api/orgs/{id}/process/download")
    public ResponseEntity<byte[]> download(@PathVariable("id") Long orgId) {
        Organization org = orgMapper.findById(orgId);
        if (org == null) {
            throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + orgId);
        }
        byte[] content = processService.downloadWorkbook(orgId);

        String filename = "권리처리_" + org.getOrgName() + ".xlsx";
        String encodedName = URLEncoder.encode(filename, StandardCharsets.UTF_8).replace("+", "%20");

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName)
                .contentType(MediaType.parseMediaType(
                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .body(content);
    }

    private static boolean hasAllowedExtension(String filename) {
        String lower = filename.toLowerCase();
        return lower.endsWith(".xlsx") || lower.endsWith(".xlsm");
    }
}
