import { sendMessage } from '../../shared/state';

type ViewMode = 'idle' | 'exporting' | 'restoring';

let mode: ViewMode = 'idle';

export function renderBackupPanel(app: HTMLElement): void {
  app.innerHTML = `
    <div class="panel">
      <h1>Backup &amp; restore</h1>

      <section class="card" id="export-card">
        <h2>Export</h2>
        <p>Pack this vault into a single encrypted <code>.relbak</code> file.
        The backup passphrase is independent of your vault passphrase.</p>
        <label><input type="checkbox" id="include-image"> Include reference image (single-file recovery)</label>
        <p class="muted">Git history is not bundled from the extension. Use the CLI if you want a full audit-log backup.</p>
        <button id="export-btn">Export backup…</button>
        <pre id="export-status" class="status hidden"></pre>
      </section>

      <section class="card" id="restore-card">
        <h2>Restore</h2>
        <p>Decrypt a <code>.relbak</code> file and push it to a fresh
        remote. The remote must be empty.</p>
        <input type="file" id="restore-file" accept=".relbak">
        <fieldset id="restore-remote" class="hidden">
          <legend>Target remote</legend>
          <label>Host type
            <select id="rt-host-type">
              <option value="gitea">Gitea</option>
              <option value="github">GitHub</option>
            </select>
          </label>
          <label>Host URL <input id="rt-host-url" type="url" placeholder="https://git.example.com"></label>
          <label>Repo path <input id="rt-repo" type="text" placeholder="user/relicario-vault"></label>
          <label>API token <input id="rt-token" type="password"></label>
          <button id="restore-btn">Restore…</button>
        </fieldset>
        <pre id="restore-status" class="status hidden"></pre>
      </section>
    </div>
  `;

  wireExport(app);
  wireRestore(app);
}

function wireExport(scope: HTMLElement): void {
  const btn = scope.querySelector('#export-btn') as HTMLButtonElement;
  const includeImage = scope.querySelector('#include-image') as HTMLInputElement;
  const status = scope.querySelector('#export-status') as HTMLElement;

  btn.addEventListener('click', async () => {
    if (mode !== 'idle') return;
    const passphrase = window.prompt('Backup passphrase (≥ zxcvbn score 3):');
    if (!passphrase) return;

    mode = 'exporting';
    btn.disabled = true;
    showStatus(status, 'Exporting…');

    try {
      const resp = await sendMessage({
        type: 'export_backup',
        passphrase,
        includeImage: includeImage.checked,
      });
      if (!resp.ok) throw new Error(resp.error);

      const data = (resp as { ok: true; data: { bytes: ArrayBuffer } }).data;
      const blob = new Blob([data.bytes], { type: 'application/octet-stream' });
      const url = URL.createObjectURL(blob);
      const ts = new Date().toISOString().replace(/[:.]/g, '-');
      const a = document.createElement('a');
      a.href = url;
      a.download = `relicario-${ts}.relbak`;
      a.click();
      setTimeout(() => URL.revokeObjectURL(url), 1000);

      showStatus(status, `Exported (${(data.bytes.byteLength / 1024 / 1024).toFixed(2)} MiB).`);
    } catch (e) {
      showStatus(status, `Failed: ${(e as Error).message}`);
    } finally {
      mode = 'idle';
      btn.disabled = false;
    }
  });
}

function wireRestore(scope: HTMLElement): void {
  const file = scope.querySelector('#restore-file') as HTMLInputElement;
  const remoteFs = scope.querySelector('#restore-remote') as HTMLElement;
  const btn = scope.querySelector('#restore-btn') as HTMLButtonElement;
  const status = scope.querySelector('#restore-status') as HTMLElement;

  file.addEventListener('change', () => {
    remoteFs.classList.toggle('hidden', file.files == null || file.files.length === 0);
  });

  btn.addEventListener('click', async () => {
    if (mode !== 'idle') return;
    const f = file.files?.[0];
    if (!f) return;

    const passphrase = window.prompt('Backup passphrase:');
    if (!passphrase) return;

    const hostType = (scope.querySelector('#rt-host-type') as HTMLSelectElement).value as 'gitea' | 'github';
    const hostUrl = (scope.querySelector('#rt-host-url') as HTMLInputElement).value.trim();
    const repoPath = (scope.querySelector('#rt-repo') as HTMLInputElement).value.trim();
    const apiToken = (scope.querySelector('#rt-token') as HTMLInputElement).value.trim();
    if (!hostUrl || !repoPath || !apiToken) {
      showStatus(status, 'fill in host URL, repo path, and API token');
      return;
    }

    mode = 'restoring';
    btn.disabled = true;
    showStatus(status, 'Restoring…');

    try {
      const bytes = await f.arrayBuffer();
      const resp = await sendMessage({
        type: 'restore_backup',
        bytes,
        passphrase,
        newRemote: { hostType, hostUrl, repoPath, apiToken },
      });
      if (!resp.ok) throw new Error(resp.error);

      const data = (resp as { ok: true; data: { summary: { itemCount: number; attachmentCount: number; hasImage: boolean } } }).data;
      const summary = data.summary;
      showStatus(status, `Restored: ${summary.itemCount} items, ${summary.attachmentCount} attachments${summary.hasImage ? ', image included' : ''}. Reload the extension and unlock.`);
    } catch (e) {
      showStatus(status, `Failed: ${(e as Error).message}`);
    } finally {
      mode = 'idle';
      btn.disabled = false;
    }
  });
}

function showStatus(el: HTMLElement, text: string): void {
  el.textContent = text;
  el.classList.remove('hidden');
}

export function teardown(): void {
  // No timers / object URLs to clean up — Blob URL revocation is per-export.
  mode = 'idle';
}
