<?php
require_once __DIR__ . '/lib/functions.php';
mdw_require_login();
global $mdw_site_root, $mdw_update_exclusions;
$results = [];
$mode = '';
$summary = ['add' => 0, 'update' => 0, 'skip' => 0, 'total' => 0, 'failed' => 0, 'completed_at' => '', 'version' => MDW_ADMIN_VERSION];

function mdw_rrmdir(string $dir): void {
    if (!is_dir($dir)) return;
    $items = array_diff(scandir($dir), ['.','..']);
    foreach ($items as $item) {
        $path = $dir . '/' . $item;
        is_dir($path) ? mdw_rrmdir($path) : unlink($path);
    }
    rmdir($dir);
}

function mdw_collect_files(string $dir, string $base): array {
    $files = [];
    $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS));
    foreach ($it as $file) {
        if ($file->isFile()) {
            $rel = ltrim(str_replace('\\','/', substr($file->getPathname(), strlen($base))), '/');
            $files[] = $rel;
        }
    }
    sort($files);
    return $files;
}

function mdw_copy_verified(string $source, string $target, string &$reason): bool {
    $targetDir = dirname($target);
    if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true)) {
        $reason = 'Could not create target directory.';
        return false;
    }
    if (!is_writable($targetDir)) {
        $reason = 'Target directory is not writable.';
        return false;
    }
    if (!copy($source, $target)) {
        $reason = 'PHP copy() failed.';
        return false;
    }
    clearstatcache(true, $target);
    if (!file_exists($target)) {
        $reason = 'Target file was not created.';
        return false;
    }
    if (filesize($source) !== filesize($target)) {
        $reason = 'Copied file size did not match source.';
        return false;
    }
    $reason = 'Copied and verified.';
    return true;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $mode = $_POST['mode'] ?? 'dryrun';
    if (empty($_FILES['updatezip']['tmp_name'])) {
        mdw_flash('Choose a ZIP file first.', 'error');
        header('Location: updater.php'); exit;
    }
    $ext = strtolower(pathinfo($_FILES['updatezip']['name'], PATHINFO_EXTENSION));
    if ($ext !== 'zip') {
        mdw_flash('Updater only accepts ZIP files.', 'error');
        header('Location: updater.php'); exit;
    }
    $stamp = date('Ymd-His');
    $upload = __DIR__ . '/updates/update-' . $stamp . '.zip';
    if (!is_dir(dirname($upload))) mkdir(dirname($upload), 0755, true);
    if (!move_uploaded_file($_FILES['updatezip']['tmp_name'], $upload)) {
        mdw_flash('Could not save uploaded ZIP.', 'error');
        header('Location: updater.php'); exit;
    }
    $tmp = __DIR__ . '/tmp/extract-' . $stamp;
    mkdir($tmp, 0755, true);
    $zip = new ZipArchive();
    if ($zip->open($upload) !== true) {
        mdw_flash('Could not open ZIP file.', 'error');
        header('Location: updater.php'); exit;
    }
    $zip->extractTo($tmp);
    $zip->close();

    $items = array_values(array_diff(scandir($tmp), ['.','..']));
    $source = $tmp;
    if (count($items) === 1 && is_dir($tmp . '/' . $items[0])) {
        $source = $tmp . '/' . $items[0];
    }

    $files = mdw_collect_files($source, $source);
    foreach ($files as $rel) {
        $excluded = mdw_is_excluded($rel, $mdw_update_exclusions);
        $target = rtrim($mdw_site_root, '/') . '/' . $rel;
        $action = $excluded ? 'SKIP protected' : (file_exists($target) ? 'UPDATE' : 'ADD');
        $detail = '';
        $ok = true;

        if ($excluded) { $summary['skip']++; }
        elseif ($action === 'UPDATE') { $summary['update']++; }
        elseif ($action === 'ADD') { $summary['add']++; }
        $summary['total']++;

        if ($mode === 'apply' && !$excluded) {
            $ok = mdw_copy_verified($source . '/' . $rel, $target, $detail);
            if (!$ok) {
                $summary['failed']++;
                $action = 'FAILED ' . $action;
            }
        } elseif ($mode === 'dryrun') {
            $detail = 'Dry run only. No changes made.';
        }

        $results[] = ['file' => $rel, 'status' => $action, 'ok' => $ok, 'detail' => $detail];
    }
    $summary['completed_at'] = date('M j, Y g:i A');
    mdw_rrmdir($tmp);
}

mdw_render_header('Site Updater');
?>
<section class="panel">
  <h2>Upload Site Update ZIP</h2>
  <p class="muted">Current MDW Admin version: <strong><?php echo mdw_h(MDW_ADMIN_VERSION); ?></strong></p>
  <p class="muted">Use Dry Run first. The updater skips protected folders such as <code>vsadmin/</code>, <code>clearchat/</code>, <code>public-downloads/</code>, and this admin's data/config/upload folders.</p>
  <form method="post" enctype="multipart/form-data">
    <label>Update ZIP</label>
    <input type="file" name="updatezip" accept=".zip" required><br><br>
    <button class="button" name="mode" value="dryrun" type="submit">Dry Run</button>
    <button class="button danger" name="mode" value="apply" type="submit" onclick="return confirm('Apply this ZIP to the site now? Use Dry Run first.');">Apply Update</button>
  </form>
</section>
<?php if ($results): ?>
<section class="panel <?php echo ($mode === 'apply' && $summary['failed'] === 0) ? 'update-complete' : (($summary['failed'] > 0) ? 'update-failed' : ''); ?>" style="margin-top:20px">
  <h2><?php echo $mode === 'apply' ? ($summary['failed'] ? 'Update Completed With Errors' : 'Update Complete Successfully') : 'Dry Run Results'; ?></h2>
  <?php if ($mode === 'apply'): ?>
    <p class="muted">Finished at <?php echo mdw_h($summary['completed_at']); ?>. MDW Admin version now reports: <strong><?php echo mdw_h(MDW_ADMIN_VERSION); ?></strong>.</p>
  <?php else: ?>
    <p class="muted">Dry run only. No files were changed.</p>
  <?php endif; ?>
  <div class="update-summary">
    <div class="metric"><strong><?php echo (int)$summary['add']; ?></strong><span>Files Added</span></div>
    <div class="metric"><strong><?php echo (int)$summary['update']; ?></strong><span>Files Updated</span></div>
    <div class="metric"><strong><?php echo (int)$summary['skip']; ?></strong><span>Protected Skipped</span></div>
    <div class="metric"><strong><?php echo (int)$summary['failed']; ?></strong><span>Failed Copies</span></div>
    <div class="metric"><strong><?php echo (int)$summary['total']; ?></strong><span>Total Scanned</span></div>
  </div>
  <?php if ($mode === 'apply'): ?><p><a class="button" href="index.php">Refresh Admin Dashboard</a> <a class="button ghost" href="updater.php">Run Another Update</a></p><?php endif; ?>
  <div class="file-list"><?php foreach($results as $r): ?><code class="<?php echo empty($r['ok']) ? 'copy-failed' : ''; ?>"><?php echo mdw_h($r['status']); ?> — <?php echo mdw_h($r['file']); ?><?php if (!empty($r['detail'])) echo ' — ' . mdw_h($r['detail']); ?></code><?php endforeach; ?></div>
</section>
<?php endif; ?>
<section class="panel" style="margin-top:20px"><h2>Protected Paths</h2><div class="file-list"><?php foreach($mdw_update_exclusions as $rule): ?><code><?php echo mdw_h($rule); ?></code><?php endforeach; ?></div></section>
<?php mdw_render_footer(); ?>
