<?php
// Esta etapa não inclui bootstrap.php de propósito: o banco atual precisa estar fechado
// para que a troca do arquivo SQLite seja atômica e segura.
$config=require __DIR__.'/app/config.php';
require_once __DIR__.'/app/helpers.php';
date_default_timezone_set($config['timezone']);
if(session_status()!==PHP_SESSION_ACTIVE){
    session_name($config['session_name']);
    session_set_cookie_params(['lifetime'=>0,'path'=>'/','secure'=>(!empty($_SERVER['HTTPS'])&&$_SERVER['HTTPS']!=='off'),'httponly'=>true,'samesite'=>'Lax']);
    session_start();
}
$token=(string)request('token');
$expected=(string)($_SESSION['restore_token']??'');
$pending=(string)($_SESSION['restore_pending_path']??'');
$adminId=(int)($_SESSION['restore_admin_id']??0);
if($token===''||$expected===''||!hash_equals($expected,$token)||$adminId<1){http_response_code(403);exit('Solicitação de restauração inválida ou expirada.');}
$restoreRoot=realpath(dirname($config['db_path']).'/restore');
$pendingReal=realpath($pending);
if(!$restoreRoot||!$pendingReal||strpos($pendingReal,$restoreRoot.DIRECTORY_SEPARATOR)!==0||!is_file($pendingReal)){http_response_code(400);exit('Arquivo temporário da restauração não encontrado.');}

try{
    // Revalida o arquivo antes da troca sem tocar no banco atual.
    $handle=fopen($pendingReal,'rb');$header=$handle?fread($handle,16):'';if(is_resource($handle))fclose($handle);
    if($header!=="SQLite format 3\000") throw new RuntimeException('Backup SQLite inválido.');
    $test=new PDO('sqlite:'.$pendingReal);$test->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $integrity=(string)$test->query('PRAGMA integrity_check')->fetchColumn();
    if(strtolower(trim($integrity))!=='ok') throw new RuntimeException('Falha de integridade do backup: '.$integrity);
    $admins=(int)$test->query("SELECT COUNT(*) FROM users WHERE role='super_admin'")->fetchColumn();
    if($admins<1) throw new RuntimeException('O backup não contém uma conta Adminitrador Sênior.');
    $test=null;

    $dbPath=$config['db_path'];$dir=dirname($dbPath);
    if(!is_dir($dir)||!is_writable($dir)) throw new RuntimeException('A pasta storage não possui permissão de escrita.');
    $newPath=$dbPath.'.restore-new';$oldPath=$dbPath.'.restore-old';
    @unlink($newPath);@unlink($oldPath);
    if(!copy($pendingReal,$newPath)) throw new RuntimeException('Não foi possível preparar o novo banco.');
    @chmod($newPath,0640);
    // Remove arquivos de WAL/SHM do banco anterior; nenhum PDO do banco atual foi aberto neste request.
    @unlink($dbPath.'-wal');@unlink($dbPath.'-shm');
    if(is_file($dbPath) && !rename($dbPath,$oldPath)) throw new RuntimeException('Não foi possível reservar o banco atual para a troca.');
    if(!rename($newPath,$dbPath)){
        if(is_file($oldPath)) @rename($oldPath,$dbPath);
        throw new RuntimeException('Não foi possível ativar o banco restaurado. O banco anterior foi recuperado.');
    }
    @unlink($oldPath);@unlink($pendingReal);@chmod($dbPath,0640);
    $source=(string)($_SESSION['restore_source_name']??'backup');
    $safety=(string)($_SESSION['restore_safety_backup']??'');
    unset($_SESSION['restore_token'],$_SESSION['restore_pending_path'],$_SESSION['restore_admin_id'],$_SESSION['restore_source_name'],$_SESSION['restore_safety_backup'],$_SESSION['user_id']);
    $_SESSION['flash'][]=['type'=>'success','message'=>'Backup restaurado com sucesso. Fonte: '.$source.($safety!==''?' • Cópia do banco anterior: '.$safety:'')];
    header('Location: '.url('login.php'));exit;
}catch(Throwable $e){
    @unlink($pendingReal);
    unset($_SESSION['restore_token'],$_SESSION['restore_pending_path'],$_SESSION['restore_admin_id'],$_SESSION['restore_source_name']);
    $_SESSION['flash'][]=['type'=>'error','message'=>'Não foi possível restaurar o backup: '.$e->getMessage()];
    header('Location: '.url('dashboard.php?page=backups'));exit;
}
