<?php
// includes/FileUpload.php - 파일 업로드 처리 클래스

class FileUpload {
    private $pdo;
    private $allowedExtensions;
    private $maxFileSize;
    
    public function __construct() {
        global $pdo;
        $this->pdo = $pdo;
        
        // PDO가 없으면 직접 생성
        if (!$this->pdo) {
            try {
                require_once __DIR__ . '/../config.php';
                $this->pdo = $pdo;
            } catch (Exception $e) {
                error_log('FileUpload PDO connection error: ' . $e->getMessage());
            }
        }
        
        // 허용된 확장자
        $this->allowedExtensions = [
            // 이미지
            'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg',
            // 문서
            'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'hwp', 'txt', 'rtf',
            // 압축
            'zip', 'rar', '7z', 'tar', 'gz',
            // 오디오
            'mp3', 'wav', 'ogg', 'm4a',
            // 비디오
            'mp4', 'avi', 'mov', 'wmv',
            // 코드/스크립트
            'js', 'php', 'html', 'css', 'json', 'xml', 'sql', 'py', 'java', 'cpp', 'c', 'h',
            // 기타
            'csv', 'tsv'
        ];
        
        // 최대 파일 크기 (10MB)
        $this->maxFileSize = 10 * 1024 * 1024;
    }
    
    /**
     * PDO 설정
     */
    public function setPdo($pdo) {
        $this->pdo = $pdo;
    }
    
    /**
     * 파일 업로드 처리
     */
    public function uploadFiles($postId, $files) {
        if (empty($files['name'][0])) {
            return false;
        }
        
        $uploadedFiles = [];
        $fileCount = count($files['name']);
        
        for ($i = 0; $i < $fileCount; $i++) {
            if ($files['error'][$i] === UPLOAD_ERR_OK) {
                $result = $this->uploadSingleFile($postId, [
                    'name' => $files['name'][$i],
                    'type' => $files['type'][$i],
                    'tmp_name' => $files['tmp_name'][$i],
                    'error' => $files['error'][$i],
                    'size' => $files['size'][$i]
                ]);
                
                if ($result) {
                    $uploadedFiles[] = $result;
                }
            }
        }
        
        return $uploadedFiles;
    }
    
    /**
     * 단일 파일 업로드
     */
    private function uploadSingleFile($postId, $file) {
        try {
            // 파일 검증
            if (!$this->validateFile($file)) {
                return false;
            }
            
            // 업로드 디렉토리 생성
            $uploadDir = $this->createUploadDirectory($postId);
            if (!$uploadDir) {
                return false;
            }
            
            // 파일명 생성
            $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
            $filename = uniqid() . '_' . time() . '.' . $extension;
            $filepath = $uploadDir . '/' . $filename;
            
            // 파일 이동
            if (!move_uploaded_file($file['tmp_name'], $filepath)) {
                error_log('File upload failed: ' . $file['name']);
                return false;
            }
            
            // 이미지인 경우 썸네일 생성
            $thumbnail = null;
            if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
                $thumbnail = $this->createThumbnail($filepath, $uploadDir, $extension);
            }
            
            // DB에 파일 정보 저장
            $relativePath = 'uploads/posts/' . $postId . '/' . date('Y/m') . '/' . $filename;
            $fileId = $this->saveFileToDatabase($postId, $file, $relativePath, $thumbnail);
            
            if ($fileId) {
                return [
                    'id' => $fileId,
                    'original_name' => $file['name'],
                    'saved_name' => $filename,
                    'file_path' => $relativePath,
                    'file_size' => $file['size'],
                    'thumbnail' => $thumbnail
                ];
            }
            
            return false;
            
        } catch (Exception $e) {
            error_log('File upload error: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 파일 검증
     */
    private function validateFile($file) {
        // 파일 크기 검증
        if ($file['size'] > $this->maxFileSize) {
            error_log('File too large: ' . $file['name']);
            return false;
        }
        
        // 확장자 검증
        $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($extension, $this->allowedExtensions)) {
            error_log('Invalid file extension: ' . $extension);
            return false;
        }
        
        // MIME 타입 검증 (확장자 검증이 더 엄격하므로 MIME 타입은 선택적 검증)
        $allowedMimes = [
            // 이미지
            'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
            // 문서
            'application/pdf',
            'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'text/plain', 'text/html', 'text/css', 'text/javascript', 'application/json', 'application/xml',
            // 압축
            'application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed',
            // 오디오
            'audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/mp4',
            // 비디오
            'video/mp4', 'video/avi', 'video/quicktime', 'video/x-ms-wmv',
            // 코드/스크립트
            'application/javascript', 'text/javascript', 'application/x-php', 'text/x-php',
            'text/x-sql', 'text/x-python', 'text/x-java-source', 'text/x-c++src', 'text/x-csrc',
            // 기타
            'text/csv', 'text/tab-separated-values'
        ];
        
        // MIME 타입 검증은 선택적 (확장자 검증이 통과했으면 MIME 타입이 없어도 허용)
        // 일부 브라우저/서버에서 MIME 타입을 잘못 감지할 수 있으므로 확장자 검증을 우선함
        if (!empty($file['type']) && !in_array($file['type'], $allowedMimes)) {
            // MIME 타입이 허용 목록에 없어도 확장자 검증을 통과했으면 경고만 하고 허용
            error_log('Warning: MIME type not in allowed list but extension is valid: ' . $file['type'] . ' for file: ' . $file['name']);
        }
        
        return true;
    }
    
    /**
     * 업로드 디렉토리 생성
     */
    private function createUploadDirectory($postId) {
        $uploadPath = __DIR__ . '/../uploads/posts/' . $postId . '/' . date('Y/m');
        
        if (!is_dir($uploadPath)) {
            if (!mkdir($uploadPath, 0755, true)) {
                error_log('Failed to create upload directory: ' . $uploadPath);
                return false;
            }
        }
        
        return $uploadPath;
    }
    
    /**
     * 썸네일 생성
     */
    private function createThumbnail($filepath, $uploadDir, $extension) {
        try {
            // 이미지 정보 가져오기
            $imageInfo = getimagesize($filepath);
            if (!$imageInfo) {
                return null;
            }
            
            $width = $imageInfo[0];
            $height = $imageInfo[1];
            
            // 썸네일이 필요한 크기인지 확인 (200px 이상)
            if ($width <= 200 && $height <= 200) {
                return null;
            }
            
            // 원본 이미지 로드
            switch ($extension) {
                case 'jpg':
                case 'jpeg':
                    $source = imagecreatefromjpeg($filepath);
                    break;
                case 'png':
                    $source = imagecreatefrompng($filepath);
                    break;
                case 'gif':
                    $source = imagecreatefromgif($filepath);
                    break;
                case 'webp':
                    $source = imagecreatefromwebp($filepath);
                    break;
                default:
                    return null;
            }
            
            if (!$source) {
                return null;
            }
            
            // 썸네일 크기 계산 (비율 유지)
            $thumbWidth = 200;
            $thumbHeight = 200;
            
            if ($width > $height) {
                $thumbHeight = intval($height * $thumbWidth / $width);
            } else {
                $thumbWidth = intval($width * $thumbHeight / $height);
            }
            
            // 썸네일 생성
            $thumbnail = imagecreatetruecolor($thumbWidth, $thumbHeight);
            
            // 투명도 처리 (PNG, GIF)
            if ($extension === 'png' || $extension === 'gif') {
                imagealphablending($thumbnail, false);
                imagesavealpha($thumbnail, true);
                $transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127);
                imagefill($thumbnail, 0, 0, $transparent);
            }
            
            // 이미지 리사이즈
            imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
            
            // 썸네일 저장
            $thumbFilename = 'thumb_' . basename($filepath);
            $thumbPath = $uploadDir . '/' . $thumbFilename;
            
            switch ($extension) {
                case 'jpg':
                case 'jpeg':
                    imagejpeg($thumbnail, $thumbPath, 85);
                    break;
                case 'png':
                    imagepng($thumbnail, $thumbPath);
                    break;
                case 'gif':
                    imagegif($thumbnail, $thumbPath);
                    break;
                case 'webp':
                    imagewebp($thumbnail, $thumbPath);
                    break;
            }
            
            // 메모리 해제
            imagedestroy($source);
            imagedestroy($thumbnail);
            
            return 'uploads/posts/' . basename(dirname($uploadDir)) . '/' . date('Y/m') . '/' . $thumbFilename;
            
        } catch (Exception $e) {
            error_log('Thumbnail creation error: ' . $e->getMessage());
            return null;
        }
    }
    
    /**
     * DB에 파일 정보 저장
     */
    private function saveFileToDatabase($postId, $file, $relativePath, $thumbnail = null) {
        try {
            // 게시판 ID 가져오기
            $stmt = $this->pdo->prepare("SELECT board_id FROM " . DB_PREFIX . "posts WHERE id = ?");
            $stmt->execute([$postId]);
            $post = $stmt->fetch();
            $boardId = $post ? $post['board_id'] : null;
            
            $sql = "INSERT INTO " . DB_PREFIX . "files (
                post_id, board_id, original_name, saved_name, file_path, file_size, 
                file_type, mime_type, is_image, thumbnail, created_at
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())";
            
            $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
            $isImage = in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'webp']) ? 1 : 0;
            
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                $postId,
                $boardId,
                $file['name'],
                basename($relativePath),
                $relativePath,
                $file['size'],
                $extension,
                $file['type'],
                $isImage,
                $thumbnail
            ]);
            
            return $this->pdo->lastInsertId();
            
        } catch (Exception $e) {
            error_log('Database save error: ' . $e->getMessage());
            return false;
        }
    }
}
?>
