<?php

namespace App\Helpers;
use Exception;

class FileHandler
{

    private $allowedImageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'webp',);

    public function __construct()
    {
    }

    public function uploadSingleFile($file, $destination, $newName = null, bool $isImageCheck = false)
    {
        $fileExtension = pathinfo($file['name'], PATHINFO_EXTENSION);
        $imageResult = true;

        if ($file['error'] == UPLOAD_ERR_OK) {
            if (!$newName) {
                $newName = $file['name'];
            }

            if ($isImageCheck) {
                $imageResult = getimagesize($file['tmp_name']);
                if ($imageResult === false) {
                    return false;
                }
            }

            $uploaded = move_uploaded_file($file['tmp_name'], $destination . '/' . $newName);
            $imageResult = $uploaded && $imageResult;

            if ($imageResult) {
                return $newName;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    public function uploadFile($file, $destination, $newName = null)
    {
        // Validation and error handling (replace with your own)
        if (empty($file) || empty($destination)) {
            throw new Exception('Invalid file or destination path provided.');
        }

        // Check if the file was uploaded successfully
        if (!isset($_FILES[$file]) || $_FILES[$file]['error'] !== UPLOAD_ERR_OK) {
            throw new Exception('File upload failed.');
        }

        // Determine the target filename
        $targetFilename = $newName ?? $_FILES[$file]['name'];

        // Open input and output streams
        $input = fopen($_FILES[$file]['tmp_name'], 'r');
        $output = fopen($destination . '/' . $targetFilename, 'w');

        // Stream the file contents
        stream_copy_to_stream($input, $output);

        // Close streams
        fclose($input);
        fclose($output);

        // Optional: Remove temporary file
        unlink($_FILES[$file]['tmp_name']);

        return $targetFilename;  // Return the final filename for reference
    }


    public function uploadMultipleFiles($files, $destination, $newNames = null)
    {
        $successCount = 0;
        foreach ($files['name'] as $key => $value) {
            $fileExtension = pathinfo($files['name'], PATHINFO_EXTENSION);
            if ($files['error'][$key] == UPLOAD_ERR_OK) {
                $newName = isset($newNames[$key]) ? $newNames[$key] : $files['name'][$key];
                move_uploaded_file($files['tmp_name'][$key], $destination . '/' . $newName . '.' . $fileExtension);
                $successCount++;
            }
        }
        return $successCount;
    }

    public function deleteFile($file)
    {
        if (file_exists($file)) {
            unlink($file);
            return true;
        }
        return false;
    }

    public function renameFile($oldName, $newName)
    {
        if (file_exists($oldName)) {
            rename($oldName, $newName);
            return true;
        }
        return false;
    }

    public function renameDirectory($oldName, $newName)
    {
        if (is_dir($oldName)) {
            rename($oldName, $newName);
            return true;
        }
        return false;
    }

    public function createDirectory($directoryName)
    {
        if (!is_dir($directoryName)) {
            mkdir($directoryName, 0777, true);
            return true;
        }
        return false;
    }

    public function deleteDirectory($directory)
    {
        if (is_dir($directory)) {
            $files = scandir($directory);
            foreach ($files as $file) {
                if ($file != '.' && $file != '..') {
                    $this->deleteDirectory($directory . DIRECTORY_SEPARATOR . $file);
                }
            }
            rmdir($directory);
            return true;
        }
        return false;
    }

    public function checkFileSize($file, $sizeInMb)
    {
        $fileSize = filesize($file);
        $allowedSize = $sizeInMb * 1024 * 1024;
        if ($fileSize <= $allowedSize) {
            return true;
        }
        return false;
    }

    public function checkImageResolution($file, $width, $height, string $checker = null, $tolerance = 0): bool
    {
        $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $fileExtension = pathinfo($file, PATHINFO_EXTENSION);

        if (!in_array($fileExtension, $allowedExtensions)) {
            return false;
        }

        if ($width <= 0 || $height <= 0) {
            return false; // Avoid division by zero
        }

        [$imageWidth, $imageHeight] = getimagesize($file);

        if ($checker === 'less') {
            return $imageWidth <= $width && $imageHeight <= $height;
        }

        if ($checker === 'more') {
            return $imageWidth > $width && $imageHeight > $height;
        }

        // Use tolerance for equality checks
        return abs($imageWidth - $width) <= $tolerance && abs($imageHeight - $height) <= $tolerance;
    }

    public function getImageResolution($file)
    {
        if (in_array(pathinfo($file, PATHINFO_EXTENSION), array('jpg', 'jpeg', 'png', 'gif', 'webp'))) {
            list($width, $height) = getimagesize($file);
            return array('width' => $width, 'height' => $height);
        }
        return false;
    }

    public function isImage($file)
    {
        if (!file_exists($file)) {
            return false;
        }

        $imageExtensions = array('jpg', 'jpeg', 'png', 'gif', 'webp', 'svg');
        $fileExtension = pathinfo($file, PATHINFO_EXTENSION);
        return in_array(strtolower($fileExtension), $this->allowedImageExtensions) && getimagesize($file);
    }

    public function cropImage($sourceFile, $destinationFile, $cropWidth, $cropHeight, $cropX, $cropY, $resizeWidth = null, $resizeHeight = null)
    {
        if (in_array(pathinfo($sourceFile, PATHINFO_EXTENSION), array('jpg', 'jpeg', 'png', 'gif', 'webp'))) {
            // Load the source image
            switch (pathinfo($sourceFile, PATHINFO_EXTENSION)) {
                case 'jpg':
                case 'jpeg':
                    $sourceImage = imagecreatefromjpeg($sourceFile);
                    break;
                case 'png':
                    $sourceImage = imagecreatefrompng($sourceFile);
                    break;
                case 'gif':
                    $sourceImage = imagecreatefromgif($sourceFile);
                    break;
            }

            // Create a new image with the specified dimensions
            $destinationImage = imagecreatetruecolor($cropWidth, $cropHeight);

            // Crop the image
            imagecopy($destinationImage, $sourceImage, 0, 0, $cropX, $cropY, $cropWidth, $cropHeight);

            // Resize the image if desired
            if ($resizeWidth && $resizeHeight) {
                $resizedImage = imagecreatetruecolor($resizeWidth, $resizeHeight);
                imagecopyresampled($resizedImage, $destinationImage, 0, 0, 0, 0, $resizeWidth, $resizeHeight, $cropWidth, $cropHeight);
                $destinationImage = $resizedImage;
            }

            // Save the new image to the specified destination
            switch (pathinfo($destinationFile, PATHINFO_EXTENSION)) {
                case 'jpg':
                case 'jpeg':
                    imagejpeg($destinationImage, $destinationFile, 90);
                    break;
                case 'png':
                    imagepng($destinationImage, $destinationFile, 9);
                    break;
                case 'gif':
                    imagegif($destinationImage, $destinationFile);
                    break;
            }

            // Free up memory
            imagedestroy($sourceImage);
            imagedestroy($destinationImage);

            return true;
        }
        return false;
    }

    public function watermark($sourceFile, $watermarkFile, $destinationFile, $position = 'center')
    {
        // Check if the source file is an image
        if (!in_array(pathinfo($sourceFile, PATHINFO_EXTENSION), array('jpg', 'jpeg', 'png', 'gif'))) {
            return false;
        }

        // Check if the watermark file is an image
        if (!in_array(pathinfo($watermarkFile, PATHINFO_EXTENSION), array('jpg', 'jpeg', 'png', 'gif'))) {
            return false;
        }

        // Load the source image and the watermark image
        switch (pathinfo($sourceFile, PATHINFO_EXTENSION)) {
            case 'jpg':
            case 'jpeg':
                $sourceImage = imagecreatefromjpeg($sourceFile);
                break;
            case 'png':
                $sourceImage = imagecreatefrompng($sourceFile);
                break;
            case 'gif':
                $sourceImage = imagecreatefromgif($sourceFile);
                break;
        }
        $watermarkImage = imagecreatefrompng($watermarkFile);

        // Get the dimensions of the source image and the watermark image
        $sourceWidth = imagesx($sourceImage);
        $sourceHeight = imagesy($sourceImage);
        $watermarkWidth = imagesx($watermarkImage);
        $watermarkHeight = imagesy($watermarkImage);

        // Calculate the position of the watermark based on the specified position
        switch ($position) {
            case 'top-left':
                $watermarkX = 0;
                $watermarkY = 0;
                break;
            case 'top-right':
                $watermarkX = $sourceWidth - $watermarkWidth;
                $watermarkY = 0;
                break;
            case 'bottom-left':
                $watermarkX = 0;
                $watermarkY = $sourceHeight - $watermarkHeight;
                break;
            case 'bottom-right':
                $watermarkX = $sourceWidth - $watermarkWidth;
                $watermarkY = $sourceHeight - $watermarkHeight;
                break;
            case 'center':
            default:
                $watermarkX = ($sourceWidth - $watermarkWidth) / 2;
                $watermarkY = ($sourceHeight - $watermarkHeight) / 2;
                break;
        }

        // Add the watermark to the source image
        imagecopy($sourceImage, $watermarkImage, $watermarkX, $watermarkY, 0, 0, $watermarkWidth, $watermarkHeight);

        // Save the new image to the specified destination
        switch (pathinfo($destinationFile, PATHINFO_EXTENSION)) {
            case 'jpg':
            case 'jpeg':
                imagejpeg($sourceImage, $destinationFile, 90);
                break;
            case 'png':
                imagepng($sourceImage, $destinationFile, 9);
                break;
            case 'gif':
                imagegif($sourceImage, $destinationFile);
                break;
        }

        // Free up memory
        imagedestroy($sourceImage);
        imagedestroy($watermarkImage);

        return true;
    }

    public function compressImage($sourceFile, $destinationFile, $quality = 80)
    {
        // Check if the source file is an image
        if (!in_array(pathinfo($sourceFile, PATHINFO_EXTENSION), array('jpg', 'jpeg', 'png', 'gif'))) {
            return false;
        }

        // Load the source image
        switch (pathinfo($sourceFile, PATHINFO_EXTENSION)) {
            case 'jpg':
            case 'jpeg':
                $image = imagecreatefromjpeg($sourceFile);
                break;
            case 'png':
                $image = imagecreatefrompng($sourceFile);
                break;
            case 'gif':
                $image = imagecreatefromgif($sourceFile);
                break;
        }

        // Save the compressed image to the specified destination
        switch (pathinfo($destinationFile, PATHINFO_EXTENSION)) {
            case 'jpg':
            case 'jpeg':
                imagejpeg($image, $destinationFile, $quality);
                break;
            case 'png':
                imagepng($image, $destinationFile, round(9 * $quality / 100));
                break;
            case 'gif':
                imagegif($image, $destinationFile);
                break;
        }

        // Free up memory
        imagedestroy($image);

        return true;
    }

    public static function replaceFileName($filePath, $newFileName, bool $isRename = true)
    {
        // Get the directory and file extension
        $directory = pathinfo($filePath, PATHINFO_DIRNAME);
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);

        // Build the new file path with the provided file name and the original extension
        $newFilePath = $directory . '/' . $newFileName . '.' . $extension;
        $newFileWithoutPath = $newFileName . '.' . $extension;

        if ($isRename && file_exists($filePath)) {
            rename($filePath, $newFilePath);
            return $newFileWithoutPath;
        } elseif (!$isRename && file_exists($filePath)) {
            return $newFileWithoutPath;
        }

        return false; // Return false if the renaming process fails
    }
}
