<?php

namespace App\Models;

use App\Helpers\{ArrayHelper, FileHandler, DateTime};
use App\Util\Helper;
use WebPConvert\WebPConvert;
use FFMpeg\FFMpeg;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Format\Video\X264;
use FFMpeg\Format\Video\WebM;

class Uploads
{
    private function isWebpNameExist(string $filename, string $directory)
    {
        if (Helper::isFileExists($directory . $filename) && Helper::endsWith($filename, '.webp')) {
            return mt_rand(10000000, 99999999) . '-' . $filename;
        } else {
            return $filename;
        }
    }

    public function isBase64Image($base64String)
    {
        if ((strpos($base64String, 'data:image/png') !== false || strpos($base64String, 'data:image/webp') !== false || strpos($base64String, 'data:image/svg+xml') !== false) && !empty($base64String)) {
            return true;
        }

        return false; // Not a valid base64-encoded image
    }

    public function getWebpName(string $fileName): string
    {
        $name = Helper::replaceStrings($fileName, ['.jpg', '.JPG', '.jpeg', '.JPEG', '.png', '.PNG'], '.webp');
        return $name;
    }

    public function convertImageToWebp(string $fileName, string $sourceDirectory, string $storeDirectory, bool $allowWebp = false): string
    {
        $allowedExtensions = ['jpg', 'jpeg', 'png', 'svg'];
        if ($allowWebp) {
            $allowedExtensions[] = 'webp';
        }

        $fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        if (in_array($fileExtension, $allowedExtensions)) {
            $newFileName = pathinfo($fileName, PATHINFO_FILENAME) . '.webp';
            WebPConvert::convert($sourceDirectory . $fileName, $storeDirectory . $newFileName);
            return $newFileName;
        }
        return $fileName;
    }

    public function deleteExistingFile($directory, $fileName)
    {
        $filePath = $directory . $fileName;
        if (Helper::isFileExists($filePath) && Helper::hasAllowedExtension($fileName)) {
            unlink($filePath);
        }
    }

    public function isChunkFile(string $fileName): bool
    {
        $status = false;
        if (strpos($fileName, '.part') !== false) {
            $status = true;
        }

        return $status;
    }

    public function getChunkTotal(array $data): int
    {
        $totalChunk = 0;
        foreach ($data as $key => $value) {
            if (strpos($key, 'upload-total-') !== false) {
                $totalChunk = $value;
            }
        }

        return (int) $totalChunk;
    }

    public function getFileName(string $fileName): string
    {
        // get file name with the extension
        $fileName = pathinfo($fileName, PATHINFO_FILENAME);
        return $fileName;
    }

    public function uploadStream(string $fileKey, string $uploadDirectory, ?string $newFileName = null): string|false
    {

        $getName = pathinfo($_FILES[$fileKey]['name'], PATHINFO_FILENAME) ?? '';
        $getExtension = pathinfo($_FILES[$fileKey]['name'], PATHINFO_EXTENSION) ?? '';
        $getFullName = $_FILES[$fileKey]['name'] ?? '';

        if (!empty($newFileName)) {
            $getName = pathinfo($newFileName, PATHINFO_FILENAME) ?? $getName;
            $getExtension = pathinfo($newFileName, PATHINFO_EXTENSION) ?? $getExtension;
            $getFullName = $newFileName;
        }

        $source = fopen($_FILES[$fileKey]['tmp_name'], 'rb');
        if ($source === false) {
            return false;
        }

        $destination = fopen($uploadDirectory . $getFullName, 'wb');
        if ($destination === false) {
            fclose($source);
            return false;
        }

        $copied = stream_copy_to_stream($source, $destination);
        fclose($source);
        fclose($destination);

        if ($copied !== false) {
            return $getFullName;
        }

        return false;
    }

    /**
     * Uploads a file.
     *
     * @param string $fileKey The key of the uploaded file in the $_FILES array.
     * @param string $uploadDirectory The directory to upload the file to.
     * @param string|null $newFileName The new name for the file. If null, the original file name is used.
     * @return string|false The name of the uploaded file, or false if the upload failed.
     */
    public function uploadFile(string $fileKey, string $uploadDirectory, ?string $newFileName = null): string|false
    {
        $imageResult = false;

        $getName = pathinfo($_FILES[$fileKey]['name'], PATHINFO_FILENAME) ?? '';
        $getExtension = pathinfo($_FILES[$fileKey]['name'], PATHINFO_EXTENSION) ?? '';
        $getFullName = $_FILES[$fileKey]['name'] ?? '';

        if (!empty($newFileName)) {
            $getName = pathinfo($newFileName, PATHINFO_FILENAME) ?? $getName;
            $getExtension = pathinfo($newFileName, PATHINFO_EXTENSION) ?? $getExtension;
            $getFullName = $newFileName;
        }

        $uploaded = move_uploaded_file($_FILES[$fileKey]['tmp_name'], $uploadDirectory . $getFullName);
        if ($uploaded) {
            return $getFullName;
        }

        return false;
    }
}
