<?php
/**
 * SIPIUTANG — Skrip Pencadangan Basis Data (CLI / Cron)
 *
 * Dijalankan dari baris perintah atau penjadwal cron cPanel.
 * Berkas hasil pencadangan disimpan di storage/backups dan dicatat pada
 * tabel backup_logs, sama seperti pencadangan manual dari antarmuka web.
 *
 * Contoh cron cPanel — setiap hari pukul 02:00 WIB:
 *   0 2 * * * /usr/local/bin/php /home/namaakun/sipiutang/database/backup.php --quiet
 *
 * Opsi:
 *   --quiet            Hanya menampilkan pesan kesalahan (cocok untuk cron).
 *   --simpan=N         Menyimpan N berkas cadangan terbaru (menimpa pengaturan sistem).
 *   --tipe=manual      Menandai jenis pencadangan pada log (default: otomatis).
 *
 * Kode keluar: 0 = berhasil, 1 = gagal.
 */
declare(strict_types=1);

if (PHP_SAPI !== 'cli') {
    http_response_code(403);
    exit("Skrip ini hanya dapat dijalankan dari baris perintah.\n");
}

@set_time_limit(0);
@ini_set('memory_limit', '512M');

require dirname(__DIR__) . '/app/bootstrap.php';

use App\Core\Audit;
use App\Core\Config;
use App\Core\Dates;

use App\Core\Settings;
use App\Services\BackupService;

$opts  = [];
foreach (array_slice($argv, 1) as $a) {
    if (preg_match('/^--([a-z_]+)(?:=(.*))?$/', $a, $m)) $opts[$m[1]] = $m[2] ?? '1';
}
$quiet = isset($opts['quiet']);
$tipe  = ($opts['tipe'] ?? 'otomatis') === 'manual' ? 'manual' : 'otomatis';

function say(string $s): void { if (!($GLOBALS['quiet'] ?? false)) echo $s . PHP_EOL; }
function err(string $s): void { fwrite(STDERR, $s . PHP_EOL); }

$cfg = Config::get('db');
say('SIPIUTANG — Pencadangan Basis Data');
say(str_repeat('=', 58));
say('Waktu       : ' . Dates::fmtDateTime(Dates::now()));
say('Basis data  : ' . ($cfg['database'] ?? '-') . ' @ ' . ($cfg['host'] ?? '-'));

if (isset($opts['simpan']) && (int)$opts['simpan'] > 0) {
    Settings::set('backup.jumlah_disimpan', (string)(int)$opts['simpan']);
    say('Retensi     : ' . (int)$opts['simpan'] . ' berkas (dari argumen baris perintah)');
} else {
    say('Retensi     : ' . Settings::int('backup.jumlah_disimpan', 10) . ' berkas');
}

$t0 = microtime(true);
try {
    $hasil = BackupService::create($tipe);
} catch (Throwable $e) {
    err('GAGAL: ' . $e->getMessage());
    exit(1);
}
$detik = round(microtime(true) - $t0, 1);

if (empty($hasil['sukses'])) {
    err('GAGAL: pencadangan tidak dapat diselesaikan. Periksa izin folder storage/backups '
        . 'dan ketersediaan perintah mysqldump.');
    exit(1);
}

say('Metode      : ' . ($hasil['metode'] === 'mysqldump' ? 'mysqldump' : 'PDO internal (mysqldump tidak tersedia)'));
say('Berkas      : ' . $hasil['file']);
say('Ukuran      : ' . ukuranBerkas((int)$hasil['ukuran']));
say('Durasi      : ' . $detik . ' detik');
say(str_repeat('-', 58));

$sisa = glob(rtrim((string)Config::get('paths.backups'), '/') . '/backup_*.sql') ?: [];
say('Total berkas cadangan tersimpan: ' . count($sisa));
say('SELESAI: pencadangan berhasil.');

Audit::log('backup', 'backup', null, null,
    'Pencadangan terjadwal (CLI) berhasil: ' . $hasil['file'] . ' — ' . ukuranBerkas((int)$hasil['ukuran']));

exit(0);
