<?php

class Upload
{
    public function __construct()
    {
    }

    public function uploadFile($file, $destination, $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], $maxSize = 5242880)
    {
        $errors = $this->validate($file, $allowedTypes, $maxSize);

        if (!empty($errors)) {
            return ['success' => false, 'errors' => $errors];
        }

        $destPath = UPLOAD_PATH . DIRECTORY_SEPARATOR . $destination;
        if (!is_dir($destPath)) {
            mkdir($destPath, 0755, true);
        }

        $filename = $this->generateFilename($file['name']);
        $filepath = $destPath . DIRECTORY_SEPARATOR . $filename;

        if (move_uploaded_file($file['tmp_name'], $filepath)) {
            $relativePath = 'uploads/' . $destination . '/' . $filename;
            return ['success' => true, 'path' => $relativePath, 'filename' => $filename];
        }

        return ['success' => false, 'errors' => ['Failed to move uploaded file.']];
    }

    public function generateFilename($originalName)
    {
        $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
        $uniqueName = date('Ymd') . '_' . bin2hex(random_bytes(12));
        return $uniqueName . '.' . $extension;
    }

    public function delete($filepath)
    {
        $fullPath = BASE_PATH . DIRECTORY_SEPARATOR . $filepath;
        if (file_exists($fullPath) && is_file($fullPath)) {
            return unlink($fullPath);
        }
        return false;
    }

    public function validate($file, $allowedTypes, $maxSize)
    {
        $errors = [];

        if (!isset($file['error']) || !is_int($file['error'])) {
            $errors[] = 'Invalid file parameter.';
            return $errors;
        }

        switch ($file['error']) {
            case UPLOAD_ERR_OK:
                break;
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                $errors[] = 'File exceeds the maximum upload size.';
                return $errors;
            case UPLOAD_ERR_PARTIAL:
                $errors[] = 'File was only partially uploaded.';
                return $errors;
            case UPLOAD_ERR_NO_FILE:
                $errors[] = 'No file was uploaded.';
                return $errors;
            case UPLOAD_ERR_NO_TMP_DIR:
                $errors[] = 'Missing temporary folder.';
                return $errors;
            case UPLOAD_ERR_CANT_WRITE:
                $errors[] = 'Failed to write file to disk.';
                return $errors;
            default:
                $errors[] = 'Unknown upload error.';
                return $errors;
        }

        if ($file['size'] > $maxSize) {
            $errors[] = 'File size exceeds the maximum allowed (' . round($maxSize / 1024 / 1024, 1) . 'MB).';
        }

        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mimeType = $finfo->file($file['tmp_name']);
        if (!in_array($mimeType, $allowedTypes)) {
            $errors[] = 'File type "' . $mimeType . '" is not allowed.';
        }

        return $errors;
    }

    public function resize($source, $destination, $width, $height)
    {
        if (!file_exists($source)) {
            return false;
        }

        $imageInfo = getimagesize($source);
        if (!$imageInfo) {
            return false;
        }

        $origWidth = $imageInfo[0];
        $origHeight = $imageInfo[1];
        $mimeType = $imageInfo['mime'];

        switch ($mimeType) {
            case 'image/jpeg':
                $sourceImage = imagecreatefromjpeg($source);
                break;
            case 'image/png':
                $sourceImage = imagecreatefrompng($source);
                break;
            case 'image/gif':
                $sourceImage = imagecreatefromgif($source);
                break;
            case 'image/webp':
                $sourceImage = imagecreatefromwebp($source);
                break;
            default:
                return false;
        }

        if (!$sourceImage) {
            return false;
        }

        $ratio = min($width / $origWidth, $height / $origHeight);
        $newWidth = (int) round($origWidth * $ratio);
        $newHeight = (int) round($origHeight * $ratio);

        $newImage = imagecreatetruecolor($newWidth, $newHeight);

        if ($mimeType === 'image/png' || $mimeType === 'image/gif') {
            imagealphablending($newImage, false);
            imagesavealpha($newImage, true);
            $transparent = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
            imagefilledrectangle($newImage, 0, 0, $newWidth, $newHeight, $transparent);
        }

        imagecopyresampled($newImage, $sourceImage, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);

        $result = false;
        $destDir = dirname($destination);
        if (!is_dir($destDir)) {
            mkdir($destDir, 0755, true);
        }

        switch ($mimeType) {
            case 'image/jpeg':
                $result = imagejpeg($newImage, $destination, 85);
                break;
            case 'image/png':
                $result = imagepng($newImage, $destination, 8);
                break;
            case 'image/gif':
                $result = imagegif($newImage, $destination);
                break;
            case 'image/webp':
                $result = imagewebp($newImage, $destination, 85);
                break;
        }

        imagedestroy($sourceImage);
        imagedestroy($newImage);

        return $result;
    }

    public function getMimeType($filePath)
    {
        $fullPath = $filePath;
        if (!file_exists($fullPath)) {
            return false;
        }

        $finfo = new finfo(FILEINFO_MIME_TYPE);
        return $finfo->file($fullPath);
    }
}
