package com.interplug.qcast.util;

import com.interplug.qcast.config.message.Messages;
import jakarta.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RequiredArgsConstructor
public class ZipFileManager {

  @Autowired Messages message;

  /**
   * zip file을 생성하여 ZipOutputStream를 반환하는 method
   *
   * @param response HttpServletResponse
   * @param strCreateFileName 생성할 file 이름
   * @param listFile 파일 정보 목록
   */
  public void createZipFile(
      HttpServletResponse response, String strCreateFileName, List<Map<String, String>> listFile)
      throws Exception {

    // 압축될 파일명이 존재하지 않을 경우
    if (strCreateFileName == null || "".equals(strCreateFileName))
      throw new IllegalArgumentException(
          message.getMessage("common.message.data.no.exists", "file name"));

    // 파일이 존재하지 않을 경우
    if (listFile == null || listFile.size() == 0)
      throw new IllegalArgumentException(message.getMessage("common.message.no.dataDown"));

    // zip 파일명
    String strZipName = strCreateFileName + ".zip";

    // 파일이 실제로 존재하는지 확인하기 위해 카운트
    int cnt = 0;
    for (Map<String, String> mapFile : listFile) {
      String strSourceFile = mapFile.get("filename");
      Path path = Path.of(strSourceFile);
      if (path.toFile().exists()) {
        cnt++;
      }
    }

    log.debug("cnt :: " + cnt);

    // 파일이 없을 경우 상태 코드와 메시지 설정 후 종료
    if (cnt == 0) {
      response.setStatus(HttpServletResponse.SC_NO_CONTENT);
      response.getWriter().write("No files available for download.");
      response.flushBuffer();
      return; // 메서드 종료
    }

    // 파일이 있을 경우에만 ZIP 파일 생성
    response.setContentType("application/zip");
    response.setHeader("Content-Disposition", "attachment; filename=" + strZipName + ";");
    response.setStatus(HttpServletResponse.SC_OK);

    try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
      for (Map<String, String> mapFile : listFile) {
        String strDirectory = mapFile.get("directory");
        String strSourceFile = mapFile.get("filename");
        Path path = Path.of(strSourceFile);

        if (!path.toFile().exists()) {
          log.debug("파일 변환 작업중, [ " + strSourceFile + " ] 파일을 찾을 수 없습니다.");
          continue; // 파일이 없으면 스킵
        }

        try (FileInputStream fis = new FileInputStream(path.toFile())) {
          ZipEntry zipEntry = new ZipEntry(strDirectory + "\\" + path.getFileName().toString());
          zos.putNextEntry(zipEntry);

          byte[] buffer = new byte[1024];
          int length;
          while ((length = fis.read(buffer)) >= 0) {
            zos.write(buffer, 0, length);
          }
        } catch (IOException e) {
          response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
          throw new IllegalArgumentException(
              "파일 변환 작업중, [ " + strSourceFile + " ] 파일을 다운로드 할 수 없습니다.");
        } finally {
          zos.closeEntry();
        }
      }
    } catch (Exception e) {
      throw e;
    }

    response.flushBuffer();
  }
}
