package egovframework.util;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;

/**
 * packageName    : go.kr.project.batch.util
 * fileName       : ImageValidationUtil
 * author         : 개발자
 * date           : 2025-01-27
 * description    : 이미지 파일 검증 유틸리티
 * ===========================================================
 * DATE              AUTHOR             NOTE
 * -----------------------------------------------------------
 * 2025-01-27        개발자             최초 생성
 */
@Slf4j
public class ImageValidationUtil {

    /**
     * 지원되는 이미지 파일 확장자 목록
     */
    private static final List<String> SUPPORTED_IMAGE_EXTENSIONS = Arrays.asList(
        "jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "webp"
    );

    /**
     * 이미지 파일 MIME 타입 목록
     */
    private static final List<String> IMAGE_MIME_TYPES = Arrays.asList(
        "image/jpeg", "image/jpg", "image/png", "image/gif", 
        "image/bmp", "image/tiff", "image/webp"
    );

    /**
     * 파일이 이미지 파일인지 확장자로 확인합니다.
     *
     * @param fileName 파일명
     * @return 이미지 파일 여부
     */
    public static boolean isImageByExtension(String fileName) {
        if (fileName == null || fileName.trim().isEmpty()) {
            return false;
        }

        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex == -1 || lastDotIndex == fileName.length() - 1) {
            return false;
        }

        String extension = fileName.substring(lastDotIndex + 1).toLowerCase();
        return SUPPORTED_IMAGE_EXTENSIONS.contains(extension);
    }

    /**
     * 파일이 이미지 파일인지 MIME 타입으로 확인합니다.
     *
     * @param filePath 파일 경로
     * @return 이미지 파일 여부
     */
    public static boolean isImageByMimeType(Path filePath) {
        try {
            String mimeType = Files.probeContentType(filePath);
            if (mimeType == null) {
                return false;
            }
            return IMAGE_MIME_TYPES.contains(mimeType.toLowerCase());
        } catch (IOException e) {
            log.warn("MIME 타입 확인 중 오류 발생: {}", filePath, e);
            return false;
        }
    }

    /**
     * 이미지 파일이 손상되었는지 확인합니다.
     *
     * @param filePath 이미지 파일 경로
     * @return 손상 여부 (true: 손상됨, false: 정상)
     */
    public static boolean isImageCorrupted(Path filePath) {
        try {
            File imageFile = filePath.toFile();
            
            // 파일이 존재하지 않거나 크기가 0인 경우
            if (!imageFile.exists() || imageFile.length() == 0) {
                log.warn("이미지 파일이 존재하지 않거나 크기가 0입니다: {}", filePath);
                return true;
            }

            // ImageIO를 사용하여 이미지 읽기 시도
            BufferedImage image = ImageIO.read(imageFile);
            
            // 이미지를 읽을 수 없는 경우 손상된 것으로 판단
            if (image == null) {
                log.warn("이미지 파일을 읽을 수 없습니다: {}", filePath);
                return true;
            }

            // 이미지 크기가 유효하지 않은 경우
            if (image.getWidth() <= 0 || image.getHeight() <= 0) {
                log.warn("이미지 크기가 유효하지 않습니다: {} ({}x{})", 
                    filePath, image.getWidth(), image.getHeight());
                return true;
            }

            log.debug("이미지 파일 검증 성공: {} ({}x{})", 
                filePath, image.getWidth(), image.getHeight());
            return false;

        } catch (IOException e) {
            log.warn("이미지 파일 검증 중 오류 발생: {}", filePath, e);
            return true;
        } catch (Exception e) {
            log.error("이미지 파일 검증 중 예상치 못한 오류 발생: {}", filePath, e);
            return true;
        }
    }

    /**
     * 파일이 이미지 파일인지 종합적으로 확인합니다.
     * (확장자 + MIME 타입 검사)
     *
     * @param filePath 파일 경로
     * @return 이미지 파일 여부
     */
    public static boolean isImageFile(Path filePath) {
        String fileName = filePath.getFileName().toString();
        
        // 1차: 확장자 검사
        boolean isImageByExt = isImageByExtension(fileName);
        
        // 2차: MIME 타입 검사 (확장자가 이미지인 경우에만)
        boolean isImageByMime = isImageByExt && isImageByMimeType(filePath);
        
        log.debug("이미지 파일 검사 결과: {} - 확장자: {}, MIME: {}", 
            fileName, isImageByExt, isImageByMime);
        
        return isImageByMime;
    }

    /**
     * 이미지 파일의 상세 정보를 반환합니다.
     *
     * @param filePath 이미지 파일 경로
     * @return 이미지 정보 문자열
     */
    public static String getImageInfo(Path filePath) {
        try {
            BufferedImage image = ImageIO.read(filePath.toFile());
            if (image == null) {
                return "이미지 정보를 읽을 수 없음";
            }
            
            return String.format("크기: %dx%d, 타입: %d", 
                image.getWidth(), image.getHeight(), image.getType());
                
        } catch (IOException e) {
            log.warn("이미지 정보 조회 중 오류 발생: {}", filePath, e);
            return "이미지 정보 조회 실패: " + e.getMessage();
        }
    }
}