<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>File browser</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    :root {
      --brand: #0d9488;
      --brand-dark: #0f766e;
      --brand-light: #ccfbf1;
    }

    body {
      background: #f8fafc;
      font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
      color: #0f172a;
    }

    .page-wrap {
      max-width: 1100px;
      margin: 0 auto;
      padding: 2rem 1rem 3rem;
    }

    .page-header {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 1rem;
      margin-bottom: 1.5rem;
    }

    .page-title {
      font-size: 1.75rem;
      font-weight: 700;
      margin: 0;
    }

    .page-subtitle {
      color: #64748b;
      margin: 0.35rem 0 0;
    }

    .bucket-badge {
      background: var(--brand-light);
      color: var(--brand-dark);
      border: 1px solid #99f6e4;
      border-radius: 999px;
      padding: 0.45rem 0.9rem;
      font-size: 0.9rem;
      font-weight: 600;
      white-space: nowrap;
    }

    .panel {
      background: #fff;
      border: 1px solid #e2e8f0;
      border-radius: 12px;
      box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    }

    .filters {
      padding: 1.25rem;
      display: grid;
      grid-template-columns: 1fr 1fr auto;
      gap: 1rem;
      align-items: end;
    }

    .form-label {
      font-size: 0.85rem;
      font-weight: 600;
      color: #334155;
    }

    .btn-brand {
      background: var(--brand);
      border-color: var(--brand);
      color: #fff;
      min-width: 110px;
    }

    .btn-brand:hover,
    .btn-brand:focus {
      background: var(--brand-dark);
      border-color: var(--brand-dark);
      color: #fff;
    }

    .table thead th {
      font-size: 0.75rem;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      color: #64748b;
      border-bottom-color: #e2e8f0;
      background: #f8fafc;
    }

    .table tbody td {
      vertical-align: middle;
      border-bottom-color: #f1f5f9;
    }

    .empty-state {
      text-align: center;
      padding: 3rem 1rem;
      color: #64748b;
    }

    .empty-icon {
      width: 48px;
      height: 48px;
      border-radius: 12px;
      background: var(--brand-light);
      color: var(--brand-dark);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-size: 1.4rem;
      margin-bottom: 0.75rem;
    }

    .footer-bar {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0.9rem 1.25rem;
      border-top: 1px solid #e2e8f0;
      color: #64748b;
      font-size: 0.9rem;
    }

    .alert-inline {
      margin: 1rem 1.25rem 0;
    }

    @media (max-width: 768px) {
      .filters {
        grid-template-columns: 1fr;
      }

      .page-header {
        flex-direction: column;
      }
    }
  </style>
</head>
<body>
  <div class="page-wrap">
    <div class="page-header">
      <div>
        <h1 class="page-title">File browser</h1>
        <p class="page-subtitle">Browse upload objects by folder. Results load 10 at a time.</p>
      </div>
      <div class="bucket-badge" title="Storage driver: <?= esc($driver) ?>"><?= esc($bucket) ?></div>
    </div>

    <div class="panel">
      <div id="alertBox"></div>

      <div class="filters">
        <div>
          <label for="folderSelect" class="form-label">Folder</label>
          <select id="folderSelect" class="form-select">
            <option value="">Search or select folder</option>
          </select>
        </div>
        <div>
          <label for="searchInput" class="form-label">File name</label>
          <input id="searchInput" type="text" class="form-control" placeholder="Search file name...">
        </div>
        <div>
          <button id="searchBtn" class="btn btn-brand w-100">Search</button>
        </div>
      </div>

      <div class="table-responsive">
        <table class="table mb-0">
          <thead>
            <tr>
              <th>File name</th>
              <th>Size</th>
              <th>Last modified</th>
              <th>Action</th>
            </tr>
          </thead>
          <tbody id="filesBody">
            <tr>
              <td colspan="4">
                <div class="empty-state">
                  <div class="empty-icon">📁</div>
                  <div>Select a folder to load files</div>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="footer-bar">
        <div id="pageInfo">Page —</div>
        <div class="d-flex gap-2">
          <button id="prevBtn" class="btn btn-outline-secondary btn-sm" disabled>Previous</button>
          <button id="nextBtn" class="btn btn-brand btn-sm" disabled>Next</button>
        </div>
      </div>
    </div>
  </div>

  <script>
    const baseUrl = <?= json_encode(base_url()) ?>.replace(/\/$/, '');
    const apiBase = baseUrl + '/storage/browser';

    const folderSelect = document.getElementById('folderSelect');
    const searchInput = document.getElementById('searchInput');
    const searchBtn = document.getElementById('searchBtn');
    const filesBody = document.getElementById('filesBody');
    const pageInfo = document.getElementById('pageInfo');
    const prevBtn = document.getElementById('prevBtn');
    const nextBtn = document.getElementById('nextBtn');
    const alertBox = document.getElementById('alertBox');

    let currentFolder = '';
    let currentSearch = '';
    let pageNumber = 1;
    let tokenStack = [''];
    let nextToken = null;

    function showAlert(message, type = 'danger') {
      alertBox.innerHTML = `<div class="alert alert-${type} alert-inline mb-0">${message}</div>`;
    }

    function clearAlert() {
      alertBox.innerHTML = '';
    }

    function renderEmpty(message) {
      filesBody.innerHTML = `
        <tr>
          <td colspan="4">
            <div class="empty-state">
              <div class="empty-icon">📁</div>
              <div>${message}</div>
            </div>
          </td>
        </tr>`;
    }

    function renderLoading() {
      filesBody.innerHTML = `
        <tr>
          <td colspan="4" class="text-center py-4 text-muted">Loading files...</td>
        </tr>`;
    }

    function renderFiles(files) {
      if (!files.length) {
        renderEmpty('No files found in this folder');
        return;
      }

      filesBody.innerHTML = files.map((file) => {
        const openUrl = `${apiBase}/open?key=${encodeURIComponent(file.key)}`;
        const downloadUrl = `${apiBase}/download?key=${encodeURIComponent(file.key)}`;

        return `
          <tr>
            <td>${escapeHtml(file.file_name)}</td>
            <td>${escapeHtml(file.size_human)}</td>
            <td>${escapeHtml(file.last_modified || '—')}</td>
            <td>
              <a class="btn btn-sm btn-outline-primary me-1" href="${openUrl}" target="_blank" rel="noopener">Open</a>
              <a class="btn btn-sm btn-brand" href="${downloadUrl}">Download</a>
            </td>
          </tr>`;
      }).join('');
    }

    function escapeHtml(value) {
      return String(value)
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;')
        .replaceAll("'", '&#39;');
    }

    function updatePagination() {
      pageInfo.textContent = currentFolder ? `Page ${pageNumber}` : 'Page —';
      prevBtn.disabled = pageNumber <= 1;
      nextBtn.disabled = !nextToken;
    }

    async function loadFolders() {
      const response = await fetch(`${apiBase}/folders`);
      const data = await response.json();

      if (data.status !== 'success') {
        showAlert(data.message || 'Unable to load folders');
        return;
      }

      data.folders.forEach((folder) => {
        const option = document.createElement('option');
        option.value = folder.value;
        option.textContent = folder.label;
        folderSelect.appendChild(option);
      });
    }

    async function loadFiles(resetPagination = true) {
      clearAlert();

      currentFolder = folderSelect.value;
      currentSearch = searchInput.value.trim();

      if (!currentFolder) {
        renderEmpty('Select a folder to load files');
        pageNumber = 1;
        tokenStack = [''];
        nextToken = null;
        updatePagination();
        return;
      }

      if (resetPagination) {
        pageNumber = 1;
        tokenStack = [''];
      }

      renderLoading();

      const params = new URLSearchParams({
        folder: currentFolder,
        limit: '10',
      });

      if (currentSearch) {
        params.set('q', currentSearch);
      }

      const pageToken = tokenStack[tokenStack.length - 1];
      if (pageToken) {
        params.set('page_token', pageToken);
      }

      try {
        const response = await fetch(`${apiBase}/files?${params.toString()}`);
        const data = await response.json();

        if (data.status !== 'success') {
          showAlert(data.message || 'Unable to load files');
          renderEmpty('Unable to load files');
          nextToken = null;
          updatePagination();
          return;
        }

        renderFiles(data.files || []);
        nextToken = data.next_token || null;
        updatePagination();
      } catch (error) {
        showAlert('Network error while loading files');
        renderEmpty('Unable to load files');
        nextToken = null;
        updatePagination();
      }
    }

    searchBtn.addEventListener('click', () => loadFiles(true));
    searchInput.addEventListener('keydown', (event) => {
      if (event.key === 'Enter') {
        loadFiles(true);
      }
    });

    prevBtn.addEventListener('click', () => {
      if (pageNumber <= 1) {
        return;
      }

      tokenStack.pop();
      pageNumber -= 1;
      loadFiles(false);
    });

    nextBtn.addEventListener('click', () => {
      if (!nextToken) {
        return;
      }

      tokenStack.push(nextToken);
      pageNumber += 1;
      loadFiles(false);
    });

    loadFolders();
  </script>
</body>
</html>
