<?php

declare(strict_types=1);

namespace App\Services;

use Illuminate\Support\Facades\Storage;

class ThumbnailService
{
    /**
     * CDN host is read from config/cdn.php → FILES_CDN_URL env.
     * Hardcoding the domain is forbidden per upload-agent spec §3A.
     */
    protected static function cdnHost(): string
    {
        return rtrim((string) config('cdn.files_url', 'https://files.skinbase.org'), '/');
    }

    protected static function artworkPrefix(): string
    {
        return trim((string) config('uploads.object_storage.prefix', 'artworks'), '/');
    }

    /**
     * Canonical size keys: xs · sm · md · lg · xl (+ legacy thumb/sq support).
     */
    protected const VALID_SIZES = ['xs', 'sm', 'md', 'lg', 'xl', 'thumb', 'sq'];

    /** Size aliases for backwards compatibility with old callers. */
    protected const SIZE_ALIAS = ['thumb' => 'sm'];

    protected const THUMB_SIZES = [
        'xs'    => ['height' => 160,  'quality' => 74,  'dir' => 'xs'],
        'sm'    => ['height' => 320,  'quality' => 78,  'dir' => 'sm'],
        'sq'    => ['height' => 512,  'quality' => 82,  'dir' => 'sq',   'square' => true],
        'md'    => ['height' => 1024, 'quality' => 82,  'dir' => 'md'],
        'lg'    => ['height' => 1920, 'quality' => 85,  'dir' => 'lg'],
        'xl'    => ['height' => 2560, 'quality' => 90,  'dir' => 'xl'],
        // Legacy compatibility for older paths still expecting /thumb/.
        'thumb' => ['height' => 320,  'quality' => 78,  'dir' => 'sm'],
    ];

    /**
     * Build a thumbnail URL from a filePath/hash/id and ext.
     * Accepts either a direct hash string in $filePath, or an $id + $ext pair.
     * Legacy size codes (4 -> sm, others -> md) are supported.
     */
    public static function url(?string $filePath, ?int $id = null, ?string $ext = null, $size = 6): string
    {
        // If $filePath seems to be a content hash and $ext is provided, build directly
        if (!empty($filePath) && !empty($ext) && preg_match('/^[0-9a-f]{16,128}$/i', $filePath)) {
            $sizeKey = is_string($size) ? $size : (($size === 4) ? 'thumb' : 'md');
            return self::fromHash($filePath, $ext, $sizeKey) ?: '';
        }

        // Resolve by id when provided
        if ($id !== null) {
            try {
                $artClass = '\\App\\Models\\Artwork';
                if (class_exists($artClass)) {
                    $art = $artClass::where('id', $id)->orWhere('legacy_id', $id)->first();
                    if ($art) {
                        $hash = $art->hash ?? null;
                        $extToUse = $ext ?? ($art->thumb_ext ?? null);
                        $sizeKey = is_string($size) ? $size : (($size === 4) ? 'thumb' : 'md');
                        if (!empty($hash) && !empty($extToUse)) {
                            return self::fromHash($hash, $extToUse, $sizeKey) ?: '';
                        }
                    }
                }
            } catch (\Throwable $e) {
                // fallthrough to storage/filePath fallback
            }
        }

        // Fallback to Storage::url or return provided path
        if (!empty($filePath)) {
            try {
                return Storage::url($filePath);
            } catch (\Throwable $e) {
                return $filePath;
            }
        }

        return '';
    }

    /**
     * Build CDN URL from hash and extension.
     */
    public static function fromHash(?string $hash, ?string $ext, string $sizeKey = 'md'): ?string
    {
        if (empty($hash) || empty($ext)) return null;
        // Resolve alias (sm → thumb) then validate
        $sizeKey = self::SIZE_ALIAS[$sizeKey] ?? $sizeKey;
        $sizeKey = in_array($sizeKey, self::VALID_SIZES) ? $sizeKey : 'md';
        $dir = self::THUMB_SIZES[$sizeKey]['dir'] ?? $sizeKey;
        $h  = $hash;
        $h1 = substr($h, 0, 2);
        $h2 = substr($h, 2, 2);
        return sprintf('%s/%s/%s/%s/%s.%s', self::cdnHost(), self::artworkPrefix() . '/' . $dir, $h1, $h2, $h, $ext);
    }

    /**
     * Build srcset using sm and md sizes for legacy layouts.
     */
    public static function srcsetFromHash(?string $hash, ?string $ext): ?string
    {
        $a = self::fromHash($hash, $ext, 'thumb'); // 320px
        $b = self::fromHash($hash, $ext, 'md');    // 1024px
        if (!$a || !$b) return null;
        return $a . ' 320w, ' . $b . ' 1024w';
    }
}
