package com.bio.bio_backend.global.utils;

import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 파일 관련 유틸리티 클래스
 */
public class FileUtils {
    
    /**
     * 파일 유효성 검사
     */
    public static void validateFile(MultipartFile multipartFile) {
        if (multipartFile == null || multipartFile.isEmpty()) {
            throw new IllegalArgumentException("업로드할 파일이 없습니다.");
        }
    }
    
    /**
     * 파일 리스트 유효성 검사
     */
    public static void validateFileList(java.util.List<MultipartFile> files) {
        if (files == null || files.isEmpty()) {
            throw new IllegalArgumentException("업로드할 파일이 없습니다.");
        }
    }
    
    /**
     * 업로드 디렉토리 생성
     */
    public static Path createUploadDirectory(String uploadPath) throws IOException {
        Path uploadDir = Paths.get(uploadPath);
        if (!Files.exists(uploadDir)) {
            Files.createDirectories(uploadDir);
        }
        return uploadDir;
    }
    
    /**
     * 년월일 기반 업로드 디렉토리 생성
     * 예: uploads/2024/01/15/
     */
    public static Path createDateBasedUploadDirectory(String baseUploadPath) throws IOException {
        LocalDate today = LocalDate.now();
        String yearMonthDay = today.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        
        Path dateBasedPath = Paths.get(baseUploadPath, yearMonthDay);
        if (!Files.exists(dateBasedPath)) {
            Files.createDirectories(dateBasedPath);
        }
        return dateBasedPath;
    }
    
    /**
     * 년월 기반 업로드 디렉토리 생성
     * 예: uploads/2024/01/
     */
    public static Path createYearMonthUploadDirectory(String baseUploadPath) throws IOException {
        LocalDate today = LocalDate.now();
        String yearMonth = today.format(DateTimeFormatter.ofPattern("yyyy/MM"));
        
        Path yearMonthPath = Paths.get(baseUploadPath, yearMonth);
        if (!Files.exists(yearMonthPath)) {
            Files.createDirectories(yearMonthPath);
        }
        return yearMonthPath;
    }
    
    /**
     * 년 기반 업로드 디렉토리 생성
     * 예: uploads/2024/
     */
    public static Path createYearUploadDirectory(String baseUploadPath) throws IOException {
        LocalDate today = LocalDate.now();
        String year = today.format(DateTimeFormatter.ofPattern("yyyy"));
        
        Path yearPath = Paths.get(baseUploadPath, year);
        if (!Files.exists(yearPath)) {
            Files.createDirectories(yearPath);
        }
        return yearPath;
    }
    
    /**
     * 지정된 날짜로 업로드 디렉토리 생성
     * 예: uploads/2024/01/15/
     */
    public static Path createDateBasedUploadDirectory(String baseUploadPath, LocalDate date) throws IOException {
        String yearMonthDay = date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        
        Path dateBasedPath = Paths.get(baseUploadPath, yearMonthDay);
        if (!Files.exists(dateBasedPath)) {
            Files.createDirectories(dateBasedPath);
        }
        return dateBasedPath;
    }
    
    /**
     * 파일 확장자 추출
     */
    public static String extractFileExtension(String originalFileName) {
        if (originalFileName == null || !originalFileName.contains(".")) {
            return "";
        }
        return originalFileName.substring(originalFileName.lastIndexOf("."));
    }
    
    /**
     * 고유한 파일명 생성
     */
    public static String generateUniqueFileName(String fileExtension) {
        return UUID.randomUUID().toString() + fileExtension;
    }
    
    /**
     * 파일을 디스크에 저장
     */
    public static Path saveFileToDisk(MultipartFile multipartFile, Path uploadDir, String storedFileName) throws IOException {
        Path targetLocation = uploadDir.resolve(storedFileName);
        Files.copy(multipartFile.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
        return targetLocation;
    }
    
    /**
     * 원본 파일명 정리 (경로 정보 제거)
     */
    public static String cleanFileName(String originalFileName) {
        return StringUtils.cleanPath(originalFileName);
    }
    
    /**
     * 파일 크기를 사람이 읽기 쉬운 형태로 변환
     */
    public static String formatFileSize(long bytes) {
        if (bytes < 1024) return bytes + " B";
        if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
        if (bytes < 1024 * 1024 * 1024) return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
        return String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0));
    }
    
    /**
     * 파일 확장자로부터 MIME 타입 추정
     */
    public static String getMimeTypeFromExtension(String fileName) {
        if (fileName == null) return "application/octet-stream";
        
        String extension = extractFileExtension(fileName).toLowerCase();
        switch (extension) {
            case ".txt": return "text/plain";
            case ".html": case ".htm": return "text/html";
            case ".css": return "text/css";
            case ".js": return "application/javascript";
            case ".json": return "application/json";
            case ".xml": return "application/xml";
            case ".pdf": return "application/pdf";
            case ".zip": return "application/zip";
            case ".jpg": case ".jpeg": return "image/jpeg";
            case ".png": return "image/png";
            case ".gif": return "image/gif";
            case ".bmp": return "image/bmp";
            case ".svg": return "image/svg+xml";
            case ".mp4": return "video/mp4";
            case ".avi": return "video/x-msvideo";
            case ".mp3": return "audio/mpeg";
            case ".wav": return "audio/wav";
            default: return "application/octet-stream";
        }
    }
    
    /**
     * 안전한 파일명 생성 (특수문자 제거)
     */
    public static String createSafeFileName(String originalFileName) {
        if (originalFileName == null) return "";
        
        // 특수문자 제거 및 공백을 언더스코어로 변경
        String safeName = originalFileName
                .replaceAll("[^a-zA-Z0-9가-힣._-]", "_")
                .replaceAll("_+", "_")
                .trim();
        
        // 파일명이 너무 길면 자르기
        if (safeName.length() > 100) {
            String extension = extractFileExtension(safeName);
            safeName = safeName.substring(0, 100 - extension.length()) + extension;
        }
        
        return safeName;
    }
    
    /**
     * 파일이 이미지인지 확인
     */
    public static boolean isImageFile(String fileName) {
        if (fileName == null) return false;
        
        String extension = extractFileExtension(fileName).toLowerCase();
        return extension.matches("\\.(jpg|jpeg|png|gif|bmp|svg|webp)$");
    }
    
    /**
     * 파일이 문서인지 확인
     */
    public static boolean isDocumentFile(String fileName) {
        if (fileName == null) return false;
        
        String extension = extractFileExtension(fileName).toLowerCase();
        return extension.matches("\\.(pdf|doc|docx|xls|xlsx|ppt|pptx|txt|rtf)$");
    }
    
    /**
     * 파일이 압축파일인지 확인
     */
    public static boolean isArchiveFile(String fileName) {
        if (fileName == null) return false;
        
        String extension = extractFileExtension(fileName).toLowerCase();
        return extension.matches("\\.(zip|rar|7z|tar|gz|bz2)$");
    }
    
    /**
     * 현재 날짜의 년월일 문자열 반환
     * 예: "2024/01/15"
     */
    public static String getCurrentDatePath() {
        LocalDate today = LocalDate.now();
        return today.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
    }
    
    /**
     * 지정된 날짜의 년월일 문자열 반환
     * 예: "2024/01/15"
     */
    public static String getDatePath(LocalDate date) {
        return date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
    }
    
    /**
     * 파일 경로에서 년월일 정보 추출
     * 예: "uploads/2024/01/15/file.txt" -> "2024/01/15"
     */
    public static String extractDateFromPath(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return "";
        }
        
        // 정규식으로 년/월/일 패턴 찾기
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(\\d{4}/\\d{2}/\\d{2})");
        java.util.regex.Matcher matcher = pattern.matcher(filePath);
        
        if (matcher.find()) {
            return matcher.group(1);
        }
        
        return "";
    }
    
    /**
     * 년월일 폴더 구조가 유효한지 확인
     * 예: "2024/01/15" -> true, "2024/13/45" -> false
     */
    public static boolean isValidDatePath(String datePath) {
        if (datePath == null || datePath.isEmpty()) {
            return false;
        }
        
        try {
            String[] parts = datePath.split("/");
            if (parts.length != 3) {
                return false;
            }
            
            int year = Integer.parseInt(parts[0]);
            int month = Integer.parseInt(parts[1]);
            int day = Integer.parseInt(parts[2]);
            
            // 년도 범위 체크 (1900 ~ 2100)
            if (year < 1900 || year > 2100) {
                return false;
            }
            
            // 월 범위 체크 (1 ~ 12)
            if (month < 1 || month > 12) {
                return false;
            }
            
            // 일 범위 체크 (1 ~ 31)
            if (day < 1 || day > 31) {
                return false;
            }
            
            // 실제 존재하는 날짜인지 확인
            LocalDate.of(year, month, day);
            return true;
            
        } catch (Exception e) {
            return false;
        }
    }
}
