<?php
/**
 * (c) ININOUT & PYXIS. All Rights Reserved.
 * Wszelkie modyfikacje tego pliku wymagaja zgloszenia oraz zgody autorow.
 * Any modifications to this file require notification and consent of the authors.
 */
/**
 * i-BOK 5 - Backup / Restore konfiguracji panelu
 * Szyfrowanie AES-256-CBC z hasłem admina
 */

$msg = '';
$msg_type = '';

$cfg_dir = IBOK_ROOT . '/cfg';
$admin_dir = IBOK_ADMIN_DIR;
$contracts_dir = IBOK_ROOT . '/cfg/contracts';
$twofa_dir = IBOK_ROOT . '/db/2fa';

/**
 * Szyfruj dane AES-256-CBC
 */
function backup_encrypt($data, $password) {
    $salt = random_bytes(16);
    $key = hash_pbkdf2('sha256', $password, $salt, 100000, 32, true);
    $iv = random_bytes(16);
    $encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    if ($encrypted === false) return false;
    // Format: salt(16) + iv(16) + ciphertext
    return $salt . $iv . $encrypted;
}

/**
 * Odszyfruj dane AES-256-CBC
 */
function backup_decrypt($data, $password) {
    if (strlen($data) < 33) return false; // min: salt(16) + iv(16) + 1 byte
    $salt = substr($data, 0, 16);
    $iv = substr($data, 16, 16);
    $ciphertext = substr($data, 32);
    $key = hash_pbkdf2('sha256', $password, $salt, 100000, 32, true);
    $decrypted = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    return $decrypted;
}

// Eksport konfiguracji
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'export') {
    if (!csrf_validate()) {
        $msg = __('login.error_csrf');
        $msg_type = 'danger';
    } else {
        $export_password = $_POST['export_password'] ?? '';
        if (strlen($export_password) < 6) {
            $msg = __('admin.backup_password_min');
            $msg_type = 'danger';
        } else {
            $backup = [
                'version' => 'ibok5',
                'date' => date('Y-m-d H:i:s'),
                'cfg' => [],
                'admin' => [],
                'contracts' => [],
                '2fa' => [],
            ];

            // Zbierz pliki cfg/*.cfg
            if (is_dir($cfg_dir)) {
                $cfg_files = glob($cfg_dir . '/*.cfg');
                foreach ($cfg_files as $f) {
                    $content = file_get_contents($f);
                    if ($content !== false) {
                        $backup['cfg'][basename($f)] = $content;
                    }
                }
            }

            // Zbierz pliki admin/*.txt
            if (is_dir($admin_dir)) {
                $txt_files = glob($admin_dir . '/*.txt');
                foreach ($txt_files as $f) {
                    $content = file_get_contents($f);
                    if ($content !== false) {
                        $backup['admin'][basename($f)] = $content;
                    }
                }
            }

            // Zbierz pliki cfg/contracts/*.json
            if (is_dir($contracts_dir)) {
                $contract_files = glob($contracts_dir . '/*.json');
                foreach ($contract_files as $f) {
                    $content = file_get_contents($f);
                    if ($content !== false) {
                        $backup['contracts'][basename($f)] = $content;
                    }
                }
            }

            // Zbierz pliki db/2fa/*.json (sekrety TOTP, backup codes)
            if (is_dir($twofa_dir)) {
                $twofa_files = glob($twofa_dir . '/*.json');
                foreach ($twofa_files as $f) {
                    $content = file_get_contents($f);
                    if ($content !== false) {
                        $backup['2fa'][basename($f)] = $content;
                    }
                }
            }

            $json = json_encode($backup, JSON_UNESCAPED_UNICODE);
            $encrypted = backup_encrypt($json, $export_password);

            if ($encrypted === false) {
                $msg = __('admin.backup_encrypt_error');
                $msg_type = 'danger';
            } else {
                // Nagłówek IBOK5ENC + zaszyfrowane dane
                $output = 'IBOK5ENC' . $encrypted;
                $filename = 'ibok5_config_' . date('Ymd') . '.enc';

                header('Content-Type: application/octet-stream');
                header('Content-Disposition: attachment; filename="' . $filename . '"');
                header('Content-Length: ' . strlen($output));
                echo $output;
                exit;
            }
        }
    }
}

// Import konfiguracji
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'import') {
    if (ibok_is_demo()) {
        $msg = __('demo.save_blocked');
        $msg_type = 'warning';
    } elseif (!csrf_validate()) {
        $msg = __('login.error_csrf');
        $msg_type = 'danger';
    } elseif (!isset($_FILES['backup_file']) || $_FILES['backup_file']['error'] !== UPLOAD_ERR_OK) {
        $msg = __('admin.backup_no_file');
        $msg_type = 'danger';
    } else {
        $raw = file_get_contents($_FILES['backup_file']['tmp_name']);
        $import_password = $_POST['import_password'] ?? '';

        $data = null;

        // Wykryj format: zaszyfrowany (IBOK5ENC) lub stary JSON
        if (str_starts_with($raw, 'IBOK5ENC')) {
            // Zaszyfrowany backup
            if (empty($import_password)) {
                $msg = __('admin.backup_password_required');
                $msg_type = 'danger';
            } else {
                $encrypted_data = substr($raw, 8); // pomiń nagłówek
                $decrypted = backup_decrypt($encrypted_data, $import_password);
                if ($decrypted === false) {
                    $msg = __('admin.backup_decrypt_error');
                    $msg_type = 'danger';
                } else {
                    $data = json_decode($decrypted, true);
                    if (!is_array($data)) {
                        $msg = __('admin.backup_decrypt_error');
                        $msg_type = 'danger';
                    }
                }
            }
        } else {
            // Stary format — nieszyfrowany JSON (kompatybilność wsteczna)
            $data = json_decode($raw, true);
        }

        if ($data !== null) {
            if (!is_array($data) || empty($data['version']) || (!isset($data['cfg']) && !isset($data['admin']))) {
                $msg = __('admin.backup_invalid');
                $msg_type = 'danger';
            } else {
                $restored = 0;

                // Przywróć pliki cfg/
                if (!empty($data['cfg']) && is_array($data['cfg'])) {
                    if (!is_dir($cfg_dir)) {
                        @mkdir($cfg_dir, 0755, true);
                    }
                    foreach ($data['cfg'] as $filename => $file_content) {
                        $safe_name = basename($filename);
                        if (pathinfo($safe_name, PATHINFO_EXTENSION) !== 'cfg') continue;
                        if (file_put_contents($cfg_dir . '/' . $safe_name, $file_content, LOCK_EX) !== false) {
                            $restored++;
                        }
                    }
                }

                // Przywróć pliki admin/
                if (!empty($data['admin']) && is_array($data['admin'])) {
                    if (!is_dir($admin_dir)) {
                        @mkdir($admin_dir, 0755, true);
                    }
                    foreach ($data['admin'] as $filename => $file_content) {
                        $safe_name = basename($filename);
                        if (pathinfo($safe_name, PATHINFO_EXTENSION) !== 'txt') continue;
                        if (file_put_contents($admin_dir . '/' . $safe_name, $file_content, LOCK_EX) !== false) {
                            $restored++;
                        }
                    }
                }

                // Przywróć pliki cfg/contracts/
                if (!empty($data['contracts']) && is_array($data['contracts'])) {
                    if (!is_dir($contracts_dir)) {
                        @mkdir($contracts_dir, 0750, true);
                    }
                    foreach ($data['contracts'] as $filename => $file_content) {
                        $safe_name = basename($filename);
                        if (pathinfo($safe_name, PATHINFO_EXTENSION) !== 'json') continue;
                        if (file_put_contents($contracts_dir . '/' . $safe_name, $file_content, LOCK_EX) !== false) {
                            $restored++;
                        }
                    }
                }

                // Przywróć pliki db/2fa/
                if (!empty($data['2fa']) && is_array($data['2fa'])) {
                    if (!is_dir($twofa_dir)) {
                        @mkdir($twofa_dir, 0750, true);
                    }
                    foreach ($data['2fa'] as $filename => $file_content) {
                        $safe_name = basename($filename);
                        if (pathinfo($safe_name, PATHINFO_EXTENSION) !== 'json') continue;
                        if (file_put_contents($twofa_dir . '/' . $safe_name, $file_content, LOCK_EX) !== false) {
                            $restored++;
                        }
                    }
                }

                ibok_log("Przywrócono konfigurację z backupu: {$restored} plików", 'info');
                $msg = __('admin.backup_restore_success', ['count' => $restored]);
                $msg_type = 'success';
            }
        }
    }
}

// Policz pliki do eksportu
$cfg_count = is_dir($cfg_dir) ? count(glob($cfg_dir . '/*.cfg')) : 0;
$txt_count = is_dir($admin_dir) ? count(glob($admin_dir . '/*.txt')) : 0;
$contracts_count = is_dir($contracts_dir) ? count(glob($contracts_dir . '/*.json')) : 0;
$twofa_count = is_dir($twofa_dir) ? count(glob($twofa_dir . '/*.json')) : 0;
?>

<div class="fade-in">
    <h4 class="mb-4">
        <i class="bi bi-download me-2"></i> <?= __('admin.backup_cfg_title') ?>
    </h4>

    <?= ibok_help_section('admin_backup', __('help.show_help'), __('help_admin.backup_section_content')) ?>

    <?php if ($msg): ?>
        <div class="alert alert-<?= $msg_type ?> alert-dismissible fade show">
            <?= e($msg) ?>
            <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
        </div>
    <?php endif; ?>

    <div class="row g-4">
        <!-- Eksport -->
        <div class="col-lg-6">
            <div class="card h-100">
                <div class="card-header">
                    <i class="bi bi-box-arrow-up me-1"></i> <?= __('admin.backup_export') ?>
                </div>
                <div class="card-body">
                    <p class="text-muted"><?= __('admin.backup_export_desc') ?></p>
                    <ul class="list-unstyled text-muted small mb-3">
                        <li><i class="bi bi-folder me-1"></i> cfg/ &mdash; <?= $cfg_count ?> <?= $cfg_count === 1 ? 'plik' : 'plików' ?></li>
                        <li><i class="bi bi-folder me-1"></i> admin/ &mdash; <?= $txt_count ?> <?= $txt_count === 1 ? 'plik' : 'plików' ?></li>
                        <li><i class="bi bi-folder me-1"></i> cfg/contracts/ &mdash; <?= $contracts_count ?> <?= $contracts_count === 1 ? 'plik' : 'plików' ?></li>
                        <li><i class="bi bi-shield-lock me-1"></i> db/2fa/ &mdash; <?= $twofa_count ?> <?= $twofa_count === 1 ? 'plik' : 'plików' ?></li>
                    </ul>
                    <form method="post" action="admin.php?page=backup_cfg&action=export">
                        <?= csrf_field() ?>
                        <input type="hidden" name="action" value="export">
                        <div class="mb-3">
                            <label for="export_password" class="form-label">
                                <i class="bi bi-lock me-1"></i> <?= __('admin.backup_password') ?>
                            </label>
                            <input type="password" class="form-control" id="export_password" name="export_password"
                                   required minlength="6" placeholder="<?= __('admin.backup_password_placeholder') ?>">
                            <small class="text-muted"><?= __('admin.backup_password_hint') ?></small>
                        </div>
                        <button type="submit" class="btn btn-primary">
                            <i class="bi bi-shield-lock me-1"></i> <?= __('admin.backup_export') ?>
                        </button>
                    </form>
                </div>
            </div>
        </div>

        <!-- Import -->
        <div class="col-lg-6">
            <div class="card h-100">
                <div class="card-header">
                    <i class="bi bi-box-arrow-in-down me-1"></i> <?= __('admin.backup_import') ?>
                </div>
                <div class="card-body">
                    <p class="text-muted"><?= __('admin.backup_import_desc') ?></p>
                    <form method="post" action="admin.php?page=backup_cfg" enctype="multipart/form-data">
                        <?= csrf_field() ?>
                        <input type="hidden" name="action" value="import">
                        <div class="mb-3">
                            <label for="backup_file" class="form-label"><?= __('admin.select_file') ?> (.enc / .json)</label>
                            <input type="file" class="form-control" id="backup_file" name="backup_file" accept=".enc,.json" required>
                        </div>
                        <div class="mb-3">
                            <label for="import_password" class="form-label">
                                <i class="bi bi-lock me-1"></i> <?= __('admin.backup_password') ?>
                            </label>
                            <input type="password" class="form-control" id="import_password" name="import_password"
                                   placeholder="<?= __('admin.backup_password_import_placeholder') ?>">
                            <small class="text-muted"><?= __('admin.backup_password_import_hint') ?></small>
                        </div>
                        <button type="submit" class="btn btn-warning">
                            <i class="bi bi-upload me-1"></i> <?= __('admin.backup_import') ?>
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
