<?php
/**
 * Media library — admin page.
 *
 * Routes:
 *   GET  ?                      → grid of all media
 *   POST _action=upload         → upload one or more files
 *   POST _action=delete         → delete one file (refuses if in use)
 *
 * Filter:
 *   ?filter=in_use | unused | all   (defaults to 'all')
 *   ?page=N                          (1-based, 24/page)
 */

$root = realpath(__DIR__ . '/../../..');
require $root . '/config.php';

Auth::require();
Auth::requirePerm('media.view');

require_once dirname(__DIR__) . '/MediaLibrary.php';

$pageTitle  = __('media_library', 'Media library');
$currentNav = 'media-library';

$tid   = current_tenant_id();
$flash = null;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!csrf_verify()) {
        $flash = ['type' => 'error', 'msg' => __('csrf_failed', 'Security check failed.')];
    } else {
        $action = $_POST['_action'] ?? '';

        if ($action === 'upload') {
            // Require upload permission specifically (separate from view).
            if (!Auth::can('media.upload') && !Auth::isSuperAdmin()) {
                $flash = ['type' => 'error', 'msg' => __('no_permission', 'You do not have permission to upload.')];
            } else {
                // Multi-file uploads. PHP rearranges $_FILES for
                // multiple inputs with name="files[]" into per-field
                // arrays — same handling as the product gallery in
                // Shop. We process each entry independently and report
                // a count + per-file errors.
                $successCount = 0;
                $errors = [];
                if (!empty($_FILES['files']) && is_array($_FILES['files']['name'] ?? null)) {
                    $count = count($_FILES['files']['name']);
                    for ($i = 0; $i < $count; $i++) {
                        $err = $_FILES['files']['error'][$i] ?? UPLOAD_ERR_NO_FILE;
                        if ($err === UPLOAD_ERR_NO_FILE) continue;
                        if ($err !== UPLOAD_ERR_OK) {
                            $errors[] = sprintf('%s: upload error %d',
                                $_FILES['files']['name'][$i] ?? "file $i", $err);
                            continue;
                        }
                        // Stage as a single-file entry for Uploads::handle.
                        $_FILES['__media_one'] = [
                            'name'     => $_FILES['files']['name'][$i],
                            'type'     => $_FILES['files']['type'][$i],
                            'tmp_name' => $_FILES['files']['tmp_name'][$i],
                            'error'    => $_FILES['files']['error'][$i],
                            'size'     => $_FILES['files']['size'][$i],
                        ];
                        try {
                            $r = Uploads::handle('__media_one', 'shop/products', [
                                'allowed_mimes' => MediaLibrary::ALLOWED_MIMES,
                                'allowed_exts'  => MediaLibrary::ALLOWED_EXTS,
                                'max_bytes'     => 5 * 1024 * 1024,
                            ]);
                            if (!empty($r['ok'])) {
                                // Register in cache. Dimensions come from
                                // getimagesize() since Uploads::handle()
                                // doesn't provide them.
                                $w = null; $h = null;
                                $full = SLATE_ROOT . $r['path'];
                                $info = @getimagesize($full);
                                if (is_array($info)) {
                                    $w = $info[0] ?? null;
                                    $h = $info[1] ?? null;
                                }
                                MediaLibrary::register($r['path'], [
                                    'mime'          => $r['mime']     ?? '',
                                    'size_bytes'    => $r['size']     ?? 0,
                                    'width'         => $w,
                                    'height'        => $h,
                                    'original_name' => $r['original'] ?? $_FILES['files']['name'][$i],
                                ]);
                                $successCount++;
                            } else {
                                $errors[] = sprintf('%s: %s',
                                    $_FILES['files']['name'][$i] ?? "file $i",
                                    $r['error'] ?? 'unknown error');
                            }
                        } catch (\Throwable $e) {
                            $errors[] = sprintf('%s: %s',
                                $_FILES['files']['name'][$i] ?? "file $i",
                                $e->getMessage());
                        }
                        unset($_FILES['__media_one']);
                    }
                }
                if ($successCount > 0) {
                    AuditLog::record('media.uploaded', '', ['count' => $successCount]);
                    $flash = ['type' => 'success', 'msg' => sprintf(
                        __('uploaded_n', '%d file(s) uploaded.'), $successCount)];
                    if (!empty($errors)) {
                        $flash['msg'] .= ' ' . sprintf(
                            __('with_errors', 'With %d error(s); see below.'),
                            count($errors));
                        $GLOBALS['_upload_errors'] = $errors;
                    }
                } elseif (!empty($errors)) {
                    $flash = ['type' => 'error',
                        'msg' => __('uploads_failed', 'No files were uploaded.')];
                    $GLOBALS['_upload_errors'] = $errors;
                } else {
                    $flash = ['type' => 'error',
                        'msg' => __('no_files', 'Please select at least one file.')];
                }
            }
        }

        elseif ($action === 'delete') {
            if (!Auth::can('media.delete') && !Auth::isSuperAdmin()) {
                $flash = ['type' => 'error', 'msg' => __('no_permission', 'You do not have permission to delete.')];
            } else {
                $path = (string)($_POST['path'] ?? '');
                $r = MediaLibrary::delete($path);
                if ($r['ok']) {
                    AuditLog::record('media.deleted', $path);
                    $flash = ['type' => 'success', 'msg' => __('file_deleted', 'File deleted.')];
                } else {
                    $flash = ['type' => 'error', 'msg' => $r['error']];
                }
            }
        }
    }
}

// ──────────────────────────────────────────────────────────
// Listing + filter + pagination
// ──────────────────────────────────────────────────────────

$all = MediaLibrary::listAll();

// Diagnostics: figure out which DB references point to files that
// aren't on disk. This is the "phantom missing image" check — the
// most common cause of products showing a broken image even though
// their image_url is set.
$brokenRefs = MediaLibrary::collectReferences()['broken'];

// Pre-compute filter counts from the unfiltered set, before we slice
// it. Cheaper than calling listAll() twice.
$counts = ['all' => 0, 'in_use' => 0, 'unused' => 0];
foreach ($all as $f) {
    $counts['all']++;
    $counts[$f['in_use'] ? 'in_use' : 'unused']++;
}

$filter = (string)($_GET['filter'] ?? 'all');
if (!in_array($filter, ['all', 'in_use', 'unused'], true)) $filter = 'all';

if ($filter === 'in_use') {
    $all = array_values(array_filter($all, fn($f) => $f['in_use']));
} elseif ($filter === 'unused') {
    $all = array_values(array_filter($all, fn($f) => !$f['in_use']));
}

$totalCount = count($all);
$perPage    = 24;
$page       = max(1, (int)($_GET['page'] ?? 1));
$pageCount  = max(1, (int)ceil($totalCount / $perPage));
if ($page > $pageCount) $page = $pageCount;
$offset = ($page - 1) * $perPage;
$pageItems = array_slice($all, $offset, $perPage);

$canUpload = Auth::can('media.upload') || Auth::isSuperAdmin();
$canDelete = Auth::can('media.delete') || Auth::isSuperAdmin();

require $root . '/admin/partials/header.php';

if (function_exists('slate_breadcrumbs')) {
    slate_breadcrumbs([
        ['label' => 'Dashboard', 'href' => SLATE_URL . '/admin/'],
        ['label' => __('media_library', 'Media library')],
    ]);
}
?>

<?php if ($flash): ?>
    <div class="alert alert-<?= e($flash['type']) ?>" role="status"><?= e($flash['msg']) ?></div>
<?php endif; ?>

<?php if (!empty($GLOBALS['_upload_errors'])): ?>
<div class="card">
    <div class="card-header"><h2 class="text-danger">Upload errors</h2></div>
    <ul style="margin:0; padding-left:1.25rem;">
        <?php foreach ($GLOBALS['_upload_errors'] as $err): ?>
            <li class="text-sm text-danger"><?= e($err) ?></li>
        <?php endforeach; ?>
    </ul>
</div>
<?php endif; ?>

<div class="page-header">
    <div>
        <h1><?= __('media_library', 'Media library') ?></h1>
        <p class="page-header-sub">
            <?= sprintf(__('media_lib_subtitle',
                '%d image(s) in your library. Upload here once, reuse on as many products as you need.'),
                (int)$counts['all']) ?>
        </p>
    </div>
</div>

<?php if (!empty($brokenRefs)):
    // Broken references = products/variants/branding reference an
    // image path that doesn't exist on disk anymore. Most common
    // cause: an old upload that got overwritten or manually removed.
    // We show this prominently because it explains "where are my
    // product images?!" — they're in the DB but the file is gone.
?>
    <div class="card" style="border-left:4px solid #c44; background:#fff7f5;">
        <div class="card-header">
            <h2 class="text-danger">
                <?= sprintf(__('broken_refs_n', '%d broken image reference(s)'),
                    count($brokenRefs)) ?>
            </h2>
        </div>
        <p class="text-sm" style="margin-bottom:0.75rem;">
            <?= __('broken_refs_explain',
                'These products or settings point to image files that don\'t exist on disk. The product page will show a broken image. Either re-upload the missing image, or edit the product and pick a different one.') ?>
        </p>
        <table class="data-table" style="width:100%; font-size:13px;">
            <thead>
                <tr>
                    <th style="text-align:left;"><?= __('source', 'Source') ?></th>
                    <th style="text-align:left;"><?= __('name', 'Name') ?></th>
                    <th style="text-align:left;"><?= __('missing_path', 'Missing path') ?></th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
            <?php foreach ($brokenRefs as $ref): ?>
                <tr>
                    <td><code style="font-size:11px;"><?= e($ref['source']) ?></code></td>
                    <td><?= e($ref['name']) ?></td>
                    <td style="word-break:break-all; font-family:monospace; font-size:11px; color:#666;">
                        <?= e($ref['path']) ?>
                    </td>
                    <td style="text-align:right; white-space:nowrap;">
                        <?php if (str_starts_with($ref['source'], 'product')): ?>
                            <a href="<?= e(SLATE_URL) ?>/plugins/shop/admin/products.php?edit=<?= (int)$ref['id'] ?>"
                               class="btn btn-sm"><?= __('edit', 'Edit') ?></a>
                        <?php elseif ($ref['source'] === 'variant'): ?>
                            <span class="text-muted text-sm"><?= __('see_parent_product', 'see parent product') ?></span>
                        <?php elseif ($ref['source'] === 'branding'): ?>
                            <a href="<?= e(SLATE_URL) ?>/admin/settings.php"
                               class="btn btn-sm"><?= __('fix_branding', 'Fix in Settings') ?></a>
                        <?php endif; ?>
                    </td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>
    </div>
<?php endif; ?>

<?php if ($canUpload): ?>
<div class="card">
    <div class="card-header"><h2><?= __('upload_files', 'Upload files') ?></h2></div>
    <form method="post" enctype="multipart/form-data">
        <?= csrf_field() ?>
        <input type="hidden" name="_action" value="upload">
        <div class="field">
            <input type="file" name="files[]" multiple
                   accept="image/png,image/jpeg,image/webp,image/gif">
            <div class="field-hint">
                <?= __('media_upload_hint',
                    'JPG, PNG, WebP, or GIF. Max 5 MB each. Multiple files OK.') ?>
            </div>
        </div>
        <button type="submit" class="btn btn-primary"><?= __('upload', 'Upload') ?></button>
    </form>
</div>
<?php endif; ?>

<!-- Filter tabs -->
<div class="card" style="padding:0.5rem 1rem;">
    <div class="flex gap-2" style="align-items:center;">
        <span class="text-muted text-sm" style="margin-right:0.5rem;">
            <?= __('filter', 'Filter') ?>:
        </span>
        <a href="?filter=all"
           class="btn btn-sm <?= $filter === 'all' ? 'btn-primary' : '' ?>">
            <?= __('all', 'All') ?> (<?= (int)$counts['all'] ?>)
        </a>
        <a href="?filter=in_use"
           class="btn btn-sm <?= $filter === 'in_use' ? 'btn-primary' : '' ?>">
            <?= __('in_use', 'In use') ?> (<?= (int)$counts['in_use'] ?>)
        </a>
        <a href="?filter=unused"
           class="btn btn-sm <?= $filter === 'unused' ? 'btn-primary' : '' ?>">
            <?= __('unused', 'Unused') ?> (<?= (int)$counts['unused'] ?>)
        </a>
    </div>
</div>

<!-- Grid -->
<?php if (empty($pageItems)): ?>
    <div class="card">
        <div class="empty">
            <div class="empty-title"><?= __('no_media', 'No media found') ?></div>
            <p>
                <?php if ($filter !== 'all'): ?>
                    <?= __('no_media_filter',
                        'No images match this filter. Try "All".') ?>
                <?php else: ?>
                    <?= __('no_media_yet',
                        'Upload your first image above to start using the library.') ?>
                <?php endif; ?>
            </p>
        </div>
    </div>
<?php else: ?>
    <div class="card">
        <div class="media-grid"
             style="display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr));
                    gap:12px;">
            <?php foreach ($pageItems as $f):
                $sizeKb = round($f['size_bytes'] / 1024);
                $dim    = ($f['width'] && $f['height'])
                        ? $f['width'] . '×' . $f['height']
                        : '—';
            ?>
                <div class="media-card"
                     style="border:1px solid var(--border, #e5e9f0); border-radius:8px;
                            overflow:hidden; background:#fff;">
                    <div style="aspect-ratio:1; background:#f4f4f4;
                                display:flex; align-items:center; justify-content:center;">
                        <img src="<?= e($f['url']) ?>" alt="<?= e($f['original_name']) ?>"
                             loading="lazy"
                             style="max-width:100%; max-height:100%; object-fit:contain;">
                    </div>
                    <div style="padding:8px;">
                        <div style="font-size:12px; font-weight:600; word-break:break-all;
                                    margin-bottom:4px; line-height:1.3;"
                             title="<?= e($f['original_name']) ?>">
                            <?= e(mb_strimwidth($f['original_name'], 0, 24, '…')) ?>
                        </div>
                        <div class="text-muted" style="font-size:11px; line-height:1.4;">
                            <?= e($dim) ?> · <?= (int)$sizeKb ?> KB
                        </div>
                        <div style="font-size:11px; margin-top:4px;">
                            <?php if ($f['in_use']): ?>
                                <span class="badge badge-active">
                                    <?= sprintf(__('used_n', 'Used (%d)'), $f['usage_count']) ?>
                                </span>
                            <?php else: ?>
                                <span class="badge badge-muted"><?= __('unused', 'Unused') ?></span>
                            <?php endif; ?>
                        </div>
                        <div style="margin-top:8px; display:flex; gap:4px; flex-wrap:wrap;">
                            <button type="button"
                                    class="btn btn-sm copy-path-btn"
                                    data-path="<?= e($f['path']) ?>"
                                    style="flex:1; font-size:11px;"
                                    title="<?= e(__('copy_path', 'Copy the path to clipboard')) ?>">
                                <?= __('copy_path', 'Copy path') ?>
                            </button>
                            <?php if ($canDelete && !$f['in_use']): ?>
                                <form method="post" style="display:inline; margin:0;"
                                      onsubmit="return confirm(<?= e(json_encode(sprintf(
                                          __('confirm_delete', 'Delete "%s"? This removes the file from disk.'),
                                          $f['original_name']
                                      ))) ?>);">
                                    <?= csrf_field() ?>
                                    <input type="hidden" name="_action" value="delete">
                                    <input type="hidden" name="path" value="<?= e($f['path']) ?>">
                                    <button type="submit" class="btn btn-sm btn-danger"
                                            style="font-size:11px;"
                                            title="<?= e(__('delete', 'Delete')) ?>">×</button>
                                </form>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
    </div>

    <!-- Pagination -->
    <?php if ($pageCount > 1): ?>
        <div class="card" style="padding:0.5rem 1rem;">
            <div class="flex gap-2" style="align-items:center; justify-content:center;">
                <?php for ($p = 1; $p <= $pageCount; $p++): ?>
                    <a href="?filter=<?= e($filter) ?>&page=<?= $p ?>"
                       class="btn btn-sm <?= $p === $page ? 'btn-primary' : '' ?>">
                        <?= $p ?>
                    </a>
                <?php endfor; ?>
            </div>
        </div>
    <?php endif; ?>
<?php endif; ?>

<script>
// Copy-path-to-clipboard. Falls back gracefully on browsers without
// async clipboard API (Safari <13.1, very old Firefox).
document.querySelectorAll('.copy-path-btn').forEach(function (btn) {
    btn.addEventListener('click', function () {
        var path = btn.getAttribute('data-path') || '';
        if (navigator.clipboard && window.isSecureContext) {
            navigator.clipboard.writeText(path).then(function () {
                var orig = btn.textContent;
                btn.textContent = 'Copied!';
                setTimeout(function () { btn.textContent = orig; }, 1200);
            });
        } else {
            // Fallback: textarea + execCommand.
            var ta = document.createElement('textarea');
            ta.value = path;
            ta.style.position = 'fixed';
            ta.style.opacity = '0';
            document.body.appendChild(ta);
            ta.select();
            try { document.execCommand('copy'); } catch (e) {}
            document.body.removeChild(ta);
            var orig = btn.textContent;
            btn.textContent = 'Copied!';
            setTimeout(function () { btn.textContent = orig; }, 1200);
        }
    });
});
</script>

<?php require $root . '/admin/partials/footer.php'; ?>
