<?php

namespace MintyPHP\Service\Image;

trait ImageUploadTrait
{
    protected static function imageStorageBase(): string
    {
        if (defined('APP_STORAGE_PATH') && APP_STORAGE_PATH) {
            return rtrim(APP_STORAGE_PATH, '/');
        }
        return rtrim(dirname(__DIR__, 3) . '/storage', '/');
    }

    protected static function imageDetectMime(string $path): string
    {
        if (function_exists('finfo_open')) {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            if ($finfo) {
                $mime = finfo_file($finfo, $path);
                if (is_string($mime) && $mime !== '') {
                    if (self::imageIsSvgUpload($mime, $path)) {
                        return 'image/svg+xml';
                    }
                    return $mime;
                }
            }
        }
        if (self::imageIsSvgUpload('application/octet-stream', $path)) {
            return 'image/svg+xml';
        }
        return 'application/octet-stream';
    }

    protected static function imageDetectMimeSimple(string $path): string
    {
        if (function_exists('finfo_open')) {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            if ($finfo) {
                $mime = finfo_file($finfo, $path);
                if (is_string($mime) && $mime !== '') {
                    return $mime;
                }
            }
        }
        return 'application/octet-stream';
    }

    protected static function imageExtensionForMime(string $mime, bool $isSvg = false): ?string
    {
        if ($isSvg) {
            return 'svg';
        }
        $map = [
            'image/jpeg' => 'jpg',
            'image/png' => 'png',
            'image/webp' => 'webp',
        ];
        return $map[$mime] ?? null;
    }

    protected static function imageIsSvgUpload(string $mime, string $path): bool
    {
        if ($mime === 'image/svg+xml') {
            return true;
        }
        $head = @file_get_contents($path, false, null, 0, 1024);
        if (!is_string($head) || $head === '') {
            return false;
        }
        return stripos($head, '<svg') !== false;
    }

    protected static function imageIsSafeSvg(string $path): bool
    {
        $contents = @file_get_contents($path);
        if (!is_string($contents) || $contents === '') {
            return false;
        }
        $lower = strtolower($contents);
        if (strpos($lower, '<script') !== false) {
            return false;
        }
        if (strpos($lower, 'onload=') !== false) {
            return false;
        }
        if (strpos($lower, 'javascript:') !== false) {
            return false;
        }
        if (strpos($lower, '<foreignobject') !== false) {
            return false;
        }
        return true;
    }

    protected static function imageCanResize(): bool
    {
        return function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled');
    }

    protected static function imageIsValidUuid(string $uuid): bool
    {
        return (bool) preg_match('/^[a-f0-9-]{36}$/i', $uuid);
    }

    protected static function imageFindOriginalPath(string $dir): ?string
    {
        $matches = glob($dir . '/original.*');
        if (!$matches) {
            return null;
        }
        usort($matches, static function ($a, $b) {
            return filemtime($b) <=> filemtime($a);
        });
        return $matches[0];
    }

    protected static function imageCreateResource(string $path, string $mime)
    {
        if ($mime === 'image/jpeg' && function_exists('imagecreatefromjpeg')) {
            return imagecreatefromjpeg($path);
        }
        if ($mime === 'image/png' && function_exists('imagecreatefrompng')) {
            return imagecreatefrompng($path);
        }
        if ($mime === 'image/webp' && function_exists('imagecreatefromwebp')) {
            return imagecreatefromwebp($path);
        }
        return false;
    }

    protected static function imageResizeAndFit(string $sourcePath, string $targetPath, int $width, int $height, string $ext): bool
    {
        $mime = self::imageDetectMime($sourcePath);
        $src = self::imageCreateResource($sourcePath, $mime);
        if (!$src) {
            return false;
        }

        $srcWidth = imagesx($src);
        $srcHeight = imagesy($src);

        $scale = min($width / $srcWidth, $height / $srcHeight);
        $dstWidth = (int) round($srcWidth * $scale);
        $dstHeight = (int) round($srcHeight * $scale);
        if ($dstWidth < 1) {
            $dstWidth = 1;
        }
        if ($dstHeight < 1) {
            $dstHeight = 1;
        }

        $dst = imagecreatetruecolor($dstWidth, $dstHeight);
        if ($ext === 'png' || $ext === 'webp') {
            imagealphablending($dst, false);
            imagesavealpha($dst, true);
            $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
            imagefilledrectangle($dst, 0, 0, $dstWidth, $dstHeight, $transparent);
        }

        imagecopyresampled(
            $dst,
            $src,
            0,
            0,
            0,
            0,
            $dstWidth,
            $dstHeight,
            $srcWidth,
            $srcHeight
        );

        $saved = false;
        if ($ext === 'webp' && function_exists('imagewebp')) {
            $saved = imagewebp($dst, $targetPath, 82);
        } elseif ($ext === 'png' && function_exists('imagepng')) {
            $saved = imagepng($dst, $targetPath, 6);
        } else {
            $saved = imagejpeg($dst, $targetPath, 85);
        }

        if ($saved) {
            @chmod($targetPath, 0644);
        }
        return $saved;
    }

    protected static function imageResizeSquare(string $sourcePath, string $targetPath, int $size): bool
    {
        $src = self::imageLoadPng($sourcePath);
        if (!$src) {
            return false;
        }
        $srcWidth = imagesx($src);
        $srcHeight = imagesy($src);

        $cropSize = min($srcWidth, $srcHeight);
        $srcX = (int) round(($srcWidth - $cropSize) / 2);
        $srcY = (int) round(($srcHeight - $cropSize) / 2);

        $dst = imagecreatetruecolor($size, $size);
        imagealphablending($dst, false);
        imagesavealpha($dst, true);
        $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
        imagefilledrectangle($dst, 0, 0, $size, $size, $transparent);

        imagecopyresampled(
            $dst,
            $src,
            0,
            0,
            $srcX,
            $srcY,
            $size,
            $size,
            $cropSize,
            $cropSize
        );

        $saved = false;
        if (function_exists('imagepng')) {
            $saved = imagepng($dst, $targetPath, 6);
        }

        return $saved;
    }

    protected static function imageLoadPng(string $path)
    {
        if (function_exists('imagecreatefrompng')) {
            return imagecreatefrompng($path);
        }
        return false;
    }
}
