package com.kamco.cd.training.common.download;

import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourceRegion;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRange;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

@Component
public class RangeDownloadResponder {

  public ResponseEntity<?> buildZipResponse(
      Path filePath, String downloadFileName, HttpServletRequest request) throws IOException {

    if (!Files.isRegularFile(filePath)) {
      return ResponseEntity.notFound().build();
    }

    long totalSize = Files.size(filePath);
    Resource resource = new FileSystemResource(filePath);

    String disposition = "attachment; filename=\"" + downloadFileName + "\"";
    String rangeHeader = request.getHeader(HttpHeaders.RANGE);

    // 🔥 공통 헤더 (여기 고정)
    ResponseEntity.BodyBuilder base =
        ResponseEntity.ok()
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .header(HttpHeaders.CONTENT_DISPOSITION, disposition)
            .header(HttpHeaders.ACCEPT_RANGES, "bytes")
            .header("Access-Control-Expose-Headers", "Content-Disposition")
            .header("X-Accel-Buffering", "no");

    if (rangeHeader == null || rangeHeader.isBlank()) {
      return base.contentLength(totalSize).body(resource);
    }

    List<HttpRange> ranges;
    try {
      ranges = HttpRange.parseRanges(rangeHeader);
    } catch (IllegalArgumentException ex) {
      return ResponseEntity.status(416)
          .header(HttpHeaders.CONTENT_RANGE, "bytes */" + totalSize)
          .header("X-Accel-Buffering", "no")
          .build();
    }

    HttpRange range = ranges.get(0);

    long start = range.getRangeStart(totalSize);
    long end = range.getRangeEnd(totalSize);

    if (start >= totalSize) {
      return ResponseEntity.status(416)
          .header(HttpHeaders.CONTENT_RANGE, "bytes */" + totalSize)
          .header("X-Accel-Buffering", "no")
          .build();
    }

    long regionLength = end - start + 1;
    ResourceRegion region = new ResourceRegion(resource, start, regionLength);

    return ResponseEntity.status(206)
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .header(HttpHeaders.CONTENT_DISPOSITION, disposition)
        .header(HttpHeaders.ACCEPT_RANGES, "bytes")
        .header("Access-Control-Expose-Headers", "Content-Disposition")
        .header("X-Accel-Buffering", "no")
        .header(HttpHeaders.CONTENT_RANGE, "bytes " + start + "-" + end + "/" + totalSize)
        .contentLength(regionLength)
        .body(region);
  }
}
