<?php

declare(strict_types=1);

require_once dirname(__DIR__, 3) . '/system/bootstrap.php';

$currentUser = myronRequireAdministrationAccess();
$csrfToken = myronCsrfToken();
$exportService = myronSiteSnapshotExportService();
$importService = myronSiteSnapshotImportService();

myronEnsureSession();
$pending = is_array($_SESSION['myron_site_snapshot_pending_import'] ?? null)
    ? $_SESSION['myron_site_snapshot_pending_import']
    : null;

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    try {
        myronRequireCsrf($_POST['csrf_token'] ?? null);
        $action = trim((string) ($_POST['action'] ?? ''));

        if ($action === 'export-site-snapshot') {
            $snapshot = $exportService->export();
            $json = MyronSiteSnapshotEnvelope::prettyJson($snapshot);
            $timestamp = preg_replace('/[^0-9A-Za-z]+/', '-', (string) ($snapshot['exportedAt'] ?? myronNow()));
            $filename = 'myroncms-site-snapshot-' . trim((string) $timestamp, '-') . '.json';
            header('Content-Type: application/json; charset=utf-8');
            header('Content-Disposition: attachment; filename="' . str_replace('"', '', $filename) . '"');
            header('X-Content-Type-Options: nosniff');
            echo $json;
            return;
        }

        if ($action === 'dry-run-site-snapshot-import') {
            if (!myronUserHoldsScope($currentUser, MyronApiScopes::ADMINISTRATION_DESTRUCTIVE)) {
                throw new RuntimeException('Snapshot import requires destructive Administration access.');
            }
            $upload = is_array($_FILES['snapshot_file'] ?? null) ? $_FILES['snapshot_file'] : [];
            if ((int) ($upload['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
                throw new RuntimeException('Choose a snapshot JSON file to import.');
            }
            $tmpName = (string) ($upload['tmp_name'] ?? '');
            if ($tmpName === '' || !is_uploaded_file($tmpName)) {
                throw new RuntimeException('Uploaded snapshot file was not readable.');
            }
            $json = (string) file_get_contents($tmpName);
            $report = $importService->dryRun($json)->toArray();
            $_SESSION['myron_site_snapshot_pending_import'] = [
                'nonce' => bin2hex(random_bytes(16)),
                'filename' => basename((string) ($upload['name'] ?? 'snapshot.json')),
                'snapshotJsonBase64' => base64_encode($json),
                'report' => $report,
                'createdAt' => myronNow(),
            ];
            myronRedirectWithFlash(myronBuildAdminUrl('administration.snapshot'), 'Snapshot dry-run completed. Review the report before applying.', 'success');
        }

        if ($action === 'apply-site-snapshot-import') {
            if (!myronUserHoldsScope($currentUser, MyronApiScopes::ADMINISTRATION_DESTRUCTIVE)) {
                throw new RuntimeException('Snapshot import requires destructive Administration access.');
            }
            $pending = is_array($_SESSION['myron_site_snapshot_pending_import'] ?? null)
                ? $_SESSION['myron_site_snapshot_pending_import']
                : null;
            if ($pending === null) {
                throw new RuntimeException('No validated snapshot import is pending.');
            }
            if (!hash_equals((string) ($pending['nonce'] ?? ''), (string) ($_POST['nonce'] ?? ''))) {
                throw new RuntimeException('Snapshot import confirmation expired. Run dry-run again.');
            }
            if (trim((string) ($_POST['confirmation_phrase'] ?? '')) !== 'replace site') {
                throw new RuntimeException('Type "replace site" to confirm complete replacement.');
            }
            $json = base64_decode((string) ($pending['snapshotJsonBase64'] ?? ''), true);
            if (!is_string($json) || $json === '') {
                throw new RuntimeException('Pending snapshot payload could not be decoded. Run dry-run again.');
            }
            $result = $importService->apply($json);
            unset($_SESSION['myron_site_snapshot_pending_import']);
            myronRefreshSiteSettingsCache();
            myronRedirectWithFlash(
                myronBuildAdminUrl('administration.snapshot'),
                'Snapshot import applied. Replaced ' . (int) (($result['entityCounts']['pages'] ?? 0)) . ' published page(s) and related site state.',
                'success'
            );
        }

        throw new RuntimeException('Unknown snapshot action.');
    } catch (Throwable $exception) {
        myronRedirectWithFlash(myronBuildAdminUrl('administration.snapshot'), $exception->getMessage(), 'error');
    }
}

$latestExport = $exportService->export();
$counts = is_array($latestExport['entityCounts'] ?? null) ? $latestExport['entityCounts'] : [];
$pending = is_array($_SESSION['myron_site_snapshot_pending_import'] ?? null)
    ? $_SESSION['myron_site_snapshot_pending_import']
    : null;
$pendingReport = is_array($pending['report'] ?? null) ? $pending['report'] : null;

myronRenderAdminShellStart($currentUser, [
    'title' => 'Snapshot',
    'titleContext' => 'Administration',
    'activeItem' => 'snapshot',
]);
?>
<div class="mc-workspace__header">
  <?php myronRenderAdminBreadcrumbs([
      ['label' => 'Administration', 'href' => myronBuildAdminUrl('identity.users')],
      ['label' => 'System', 'href' => myronBuildAdminUrl('administration.siteSetup')],
      ['label' => 'Snapshot'],
  ]); ?>
  <div class="mc-workspace__title-row">
    <h1 class="mc-workspace__title">Snapshot</h1>
  </div>
  <p class="mc-workspace__subtitle">Export and import the operator-owned site state. Imports are complete replacement only.</p>
</div>

<div class="mc-page-canvas mc-page-canvas--site">
  <div class="sg-main">
    <section class="sg-section">
      <h2 class="sg-section__title">Export</h2>
      <p>Snapshot version <code><?= myronEscape(MyronSiteSnapshotEnvelope::SNAPSHOT_VERSION) ?></code>. Credentials, users, uploaded binaries, mail credentials, and payment secrets are excluded.</p>
      <dl class="sg-define-list">
        <dt>Published pages</dt><dd><?= (int) ($counts['pages'] ?? 0) ?></dd>
        <dt>Page templates</dt><dd><?= (int) ($counts['pageTemplates'] ?? 0) ?></dd>
        <dt>Menus</dt><dd><?= (int) ($counts['menus'] ?? 0) ?></dd>
        <dt>Token patches</dt><dd><?= (int) ($counts['tokenPatches'] ?? 0) ?></dd>
      </dl>
      <form method="post" action="<?= myronEscape(myronBuildAdminUrl('administration.snapshot')) ?>">
        <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
        <input type="hidden" name="action" value="export-site-snapshot">
        <button class="sg-button sg-button--primary" type="submit">Export Snapshot</button>
      </form>
    </section>

    <section class="sg-section">
      <h2 class="sg-section__title">Import Dry-Run</h2>
      <p>Upload a snapshot JSON file to validate it and preview replacement counts before any mutation runs.</p>
      <form class="sg-form-grid" method="post" action="<?= myronEscape(myronBuildAdminUrl('administration.snapshot')) ?>" enctype="multipart/form-data">
        <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
        <input type="hidden" name="action" value="dry-run-site-snapshot-import">
        <label class="sg-field"><span class="sg-field__label">Snapshot JSON</span>
          <input class="sg-field__control" type="file" name="snapshot_file" accept="application/json,.json" required>
        </label>
        <div class="sg-card__actions">
          <button class="sg-button sg-button--secondary" type="submit">Run Dry-Run</button>
        </div>
      </form>
    </section>

    <?php if ($pendingReport !== null): ?>
    <section class="sg-section sg-section--callout">
      <h2 class="sg-section__title">Dry-Run Report</h2>
      <p>Validated file: <strong><?= myronEscape((string) ($pending['filename'] ?? 'snapshot.json')) ?></strong>. No database mutation has run yet.</p>
      <?php $reportCounts = is_array($pendingReport['entityCounts'] ?? null) ? $pendingReport['entityCounts'] : []; ?>
      <table class="mc-page-grid">
        <thead><tr><th>Entity</th><th>Incoming count</th></tr></thead>
        <tbody>
        <?php foreach ($reportCounts as $entity => $count): ?>
        <tr><td><?= myronEscape((string) $entity) ?></td><td><?= (int) $count ?></td></tr>
        <?php endforeach; ?>
        </tbody>
      </table>
      <?php $warnings = is_array($pendingReport['warnings'] ?? null) ? $pendingReport['warnings'] : []; ?>
      <?php if ($warnings !== []): ?>
      <ul>
        <?php foreach ($warnings as $warning): ?><li><?= myronEscape((string) $warning) ?></li><?php endforeach; ?>
      </ul>
      <?php endif; ?>
      <form class="sg-form-grid" method="post" action="<?= myronEscape(myronBuildAdminUrl('administration.snapshot')) ?>">
        <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
        <input type="hidden" name="action" value="apply-site-snapshot-import">
        <input type="hidden" name="nonce" value="<?= myronEscape((string) ($pending['nonce'] ?? '')) ?>">
        <p><strong>Complete replacement:</strong> applying this snapshot replaces the covered site settings, design, page templates, published pages, menus, and navigation records.</p>
        <label class="sg-field"><span class="sg-field__label">Type replace site to confirm</span>
          <input class="sg-field__control" type="text" name="confirmation_phrase" autocomplete="off" required>
        </label>
        <div class="sg-card__actions">
          <button class="sg-button sg-button--danger" type="submit">Confirm and Apply Complete Replacement</button>
        </div>
      </form>
    </section>
    <?php endif; ?>
  </div>
</div>
<?php myronRenderAdminShellEnd(); ?>
