<?php

declare(strict_types=1);

namespace PpPhp\Plugins;

use PpPhp\Core\ViewPlugin;
use PpPhp\Core\Storage\StorageRef;
use PpPhp\Core\Storage\StorageRegistry;

/**
 * File view control.
 *
 * Renders one or many stored files (StorageRefs or legacy paths) as a tidy
 * download list: a type icon, the filename (or a custom expression), optional
 * file size, and optional inline preview for images / PDFs / audio / video.
 * URLs resolve through the storage driver so private + cloud files download
 * through the app's authorized file endpoint.
 */
class File implements ViewPlugin
{
    public static function id(): string { return 'File'; }
    public static function label(): string { return 'File Download'; }
    public static function version(): string { return '1.0.0'; }
    public static function description(): string { return 'Renders a stored file as a download link with icon and size.'; }

    private static function flag(array $s, string $key, bool $default = false): bool
    {
        if (!array_key_exists($key, $s)) return $default;
        return in_array(strtolower((string) $s[$key]), ['1', 'yes', 'true', 'on'], true);
    }

    public static function render(mixed $value, array $settings): string
    {
        $refs = StorageRef::decode($value);
        if ($refs === []) return '';

        $showSize  = self::flag($settings, 'showSize');
        $showIcon  = self::flag($settings, 'showIcon', true);
        $showThumb = self::flag($settings, 'showThumb');
        $inlinePdf = self::flag($settings, 'inlinePdf');
        $inlineMedia = self::flag($settings, 'inlineMedia');

        $out = '<div class="pp-fileview">';
        foreach ($refs as $ref) {
            $name = (string) ($ref['name'] ?? basename((string) ($ref['key'] ?? 'file')));
            $url  = self::url($ref, false);
            if ($url === '') continue;
            $ext  = strtolower((string) pathinfo($name, PATHINFO_EXTENSION));
            $isImg = StorageRef::isImage($ref);

            $out .= '<div class="pp-fv-item">';
            if ($showThumb && $isImg) {
                $t = self::url($ref, true) ?: $url;
                $out .= '<a href="' . self::esc($url) . '" target="_blank" rel="noopener"><span class="pp-fv-ic" style="width:32px;height:32px;border-radius:6px;background-image:url(' . self::esc($t) . ')"></span></a>';
            } elseif ($showIcon) {
                $out .= '<span class="pp-fv-ic pp-fv-' . self::esc(self::iconKind($name)) . '"></span>';
            }
            $out .= '<a href="' . self::esc($url) . '" target="_blank" rel="noopener">' . self::esc($name) . '</a>';
            if ($showSize && (int) ($ref['size'] ?? 0) > 0) {
                $out .= ' <span class="pp-fv-size">(' . self::esc(StorageRef::humanSize((int) $ref['size'])) . ')</span>';
            }
            $out .= '</div>';

            // Inline previews.
            if ($inlinePdf && $ext === 'pdf') {
                $out .= '<div class="pp-fv-embed"><iframe src="' . self::esc($url) . '" height="480" title="' . self::esc($name) . '"></iframe></div>';
            } elseif ($inlineMedia && in_array($ext, ['mp3', 'wav', 'ogg', 'm4a'], true)) {
                $out .= '<div class="pp-fv-embed"><audio controls src="' . self::esc($url) . '"></audio></div>';
            } elseif ($inlineMedia && in_array($ext, ['mp4', 'webm', 'mov'], true)) {
                $out .= '<div class="pp-fv-embed"><video controls src="' . self::esc($url) . '" height="320"></video></div>';
            }
        }
        $out .= '</div>';
        return $out;
    }

    private static function url(array $ref, bool $thumb): string
    {
        if (($ref['url'] ?? '') !== '') return (string) $ref['url'];
        if (class_exists(StorageRegistry::class)) {
            try { return StorageRegistry::forRef($ref)->url($ref, ['thumb' => $thumb, 'inline' => true]); }
            catch (\Throwable $e) {}
        }
        return (string) ($ref['key'] ?? '');
    }

    private static function esc(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); }

    /** File-type class suffix chosen by extension (CSS draws the glyph). */
    private static function iconKind(string $name): string
    {
        $ext = strtolower((string) pathinfo($name, PATHINFO_EXTENSION));
        if ($ext === 'pdf') return 'pdf';
        if (in_array($ext, ['doc', 'docx'], true)) return 'doc';
        if (in_array($ext, ['xls', 'xlsx', 'csv'], true)) return 'xls';
        if (in_array($ext, ['zip', 'rar', '7z', 'gz', 'tar'], true)) return 'zip';
        if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'avif'], true)) return 'img';
        if (in_array($ext, ['mp3', 'wav', 'ogg', 'm4a'], true)) return 'audio';
        if (in_array($ext, ['mp4', 'webm', 'mov', 'mkv'], true)) return 'video';
        return 'file';
    }

    public static function settingsSchema(): array
    {
        return [
            ['key' => 'showIcon', 'type' => 'bool', 'label' => 'File type icon', 'default' => 'yes', 'half' => true, 'group' => 'Display'],
            ['key' => 'showThumb', 'type' => 'bool', 'label' => 'Image thumbnails', 'default' => 'no', 'half' => true, 'group' => 'Display',
             'hint' => 'Show a small preview for image files instead of a generic icon.'],
            ['key' => 'showSize', 'type' => 'bool', 'label' => 'File size', 'default' => 'no', 'group' => 'Display', 'hint' => 'Append the size, e.g. (1.4 MB).'],
            ['key' => 'inlinePdf', 'type' => 'bool', 'label' => 'Preview PDFs inline', 'default' => 'no', 'group' => 'Preview',
             'hint' => 'Embed PDF files directly in the page.'],
            ['key' => 'inlineMedia', 'type' => 'bool', 'label' => 'Play audio / video inline', 'default' => 'no', 'group' => 'Preview',
             'hint' => 'Show a player for audio & video files.'],
        ];
    }

    public static function assets(): array { return ['js' => [], 'css' => ['assets/vendor/pp-lightbox/pp-lightbox.css']]; }
}
