<?php

namespace Idwakhalweb\Image;

class Image
{
    /**
     * Runtime cache for existence checks.
     *
     * `file_exists()` on Windows (especially under AV) can be expensive,
     * and the same image paths are frequently checked multiple times
     * during a single feed render.
     */
    protected static array $existsRuntimeCache = [];

    /**
     * Runtime cache for URL generation.
     *
     * Image::url() is called many times during feed rendering and can hit
     * file_exists() as a fallback when a CDN link isn't found.
     */
    protected static array $urlRuntimeCache = [];

    /**
     * Load a ImageProcessor for the uploaded file
     *
     * @param  bool  $isUrl
     * @return \iDwakhalweb\Image\ImageProcessor
     */
    public function load($file, $isUrl = false)
    {
        return new ImageProcessor($file, $isUrl);
    }

    /**
     * Format image url properly
     *
     * @param  string  $imagePath
     * @param  int  $size
     * @return string
     */
    public function url($imagePath, $size = 50)
    {
        $imagePath = (string) $imagePath;
        $cacheKey = $imagePath.'|'.(string) $size;
        if (array_key_exists($cacheKey, self::$urlRuntimeCache)) {
            return self::$urlRuntimeCache[$cacheKey];
        }

        $size = $this->getCorrectSize($size);

        $CDNRepository = app('App\\Repositories\\CDNRepository');

        if ($img = $CDNRepository->getLink($imagePath, $size)) {
            return self::$urlRuntimeCache[$cacheKey] = $img;
        }
        $url = str_replace('%d', $size, $imagePath);
        if (! file_exists(base_path().'/'.$url)) {
            switch ($size) {
                case 300:
                    $url = str_replace('%d', 200, $imagePath);
                    break;
                case 960:
                    $url = str_replace('%d', 'original', $imagePath);
                    break;
            }
        }

        return self::$urlRuntimeCache[$cacheKey] = \URL::to($url);
    }

    public function getCorrectSize($size)
    {
        if ($size < 50 or $size == 50) {
            return 50;
        }
        if ($size > 50 and $size < 600) {
            return 200;
        }

        return $size;
    }

    public function exists($image)
    {
        $image = (string) $image;
        if ($image === '') {
            return false;
        }

        // If it's already a URL (e.g. CDN link), don't hit the DB.
        if (filter_var($image, FILTER_VALIDATE_URL) !== false) {
            return self::$existsRuntimeCache[$image] = true;
        }

        // Normalize so different variants (leading '/', absolute URL, size suffixes)
        // share the same request-scoped cache key and DB lookup.
        $normalized = str_replace(['_600_', '_original_', '_960_'], '_%d_', $image);
        try {
            $normalized = str_replace([\URL::to('/') . '/'], [''], $normalized);
        } catch (\Throwable $e) {
            // best-effort
        }

        try {
            $CDNRepository = app('App\\Repositories\\CDNRepository');
            $normalized = $CDNRepository->convertToPath($normalized);
        } catch (\Throwable $e) {
            // best-effort
        }

        $normalized = ltrim((string) $normalized, '/');

        if (array_key_exists($normalized, self::$existsRuntimeCache)) {
            return (bool) self::$existsRuntimeCache[$normalized];
        }

        $basePath = public_path('').'/';
        if (file_exists($basePath.str_replace('%d', 50, $normalized))) {
            return self::$existsRuntimeCache[$normalized] = true;
        }
        $photoRepository = app('App\\Repositories\\PhotoRepository');

        if ($photoRepository->existsInDB($normalized)) {
            return self::$existsRuntimeCache[$normalized] = true;
        }

        return self::$existsRuntimeCache[$normalized] = false;
    }

    /**
     * delete image
     *
     * @param  string  $path
     * @return bool
     */
    public function delete($path)
    {
        $sizes = \Config::get('image.sizes');
        $CDNRepository = app('App\\Repositories\\CDNRepository');
        try {
            if ($CDNRepository->has($path)) {
                $CDNRepository->delete($path, $sizes);

                return true;
            }
            $basePath = public_path('').'/';
            if (preg_match('#%d#', $path)) {
                foreach ($sizes as $size) {
                    $filePath = $basePath.str_replace('%d', $size, $path);

                    if (file_exists($filePath)) {
                        \File::delete($filePath);
                    }
                }

                $originalPath = $basePath.str_replace('%d', 'original', $path);
                if (file_exists($originalPath)) {
                    \File::delete($originalPath);
                }
            } else {
                $path = $basePath.$path;

                if (file_exists($path)) {
                    \File::delete($path);
                }
            }
        } catch (\Exception $e) {
        }

        return true;
    }
}
