<?php
namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Csrf;
use App\Core\Permission;
use App\Models\BackupJob;
use App\Services\BackupService;
use Throwable;

final class BackupController extends Controller
{
    public function index(): void
    {
        Auth::requireLogin();
        Permission::require('backups.view');

        $service = new BackupService();

        $this->view('backups/index', [
            'pageTitle' => 'Centre de sauvegarde',
            'jobs' => BackupJob::all(),
            'dbName' => $_ENV['DB_NAME'] ?? '',
            'diagnostic' => $service->diagnostic(),
        ]);
    }

    public function create(): void
    {
        Auth::requireLogin();
        Permission::require('backups.create');
        Csrf::verify($_POST['_csrf'] ?? null);

        try {
            (new BackupService())->create(
                (int)Auth::id()
            );

            $_SESSION['success'] =
                'Instantané fidèle de la version actuellement installée créé.';
        } catch (Throwable $error) {
            $_SESSION['error'] =
                'Échec : ' . $error->getMessage();
        }

        $this->redirect('/studio/sauvegardes');
    }

    public function restore(): void
    {
        Auth::requireLogin();
        Permission::require('backups.restore');
        Permission::requireSuperAdmin();
        Auth::requireRecentAuthentication();
        Csrf::verify($_POST['_csrf'] ?? null);

        try {
            (new BackupService())->restore(
                (int)($_POST['id'] ?? 0)
            );

            $_SESSION['success'] =
                'Sauvegarde restaurée.';
        } catch (Throwable $error) {
            $_SESSION['error'] =
                'Échec : ' . $error->getMessage();
        }

        $this->redirect('/studio/sauvegardes');
    }

    public function delete(): void
    {
        Auth::requireLogin();
        Permission::require('backups.delete');
        Permission::requireSuperAdmin();
        Auth::requireRecentAuthentication();
        Csrf::verify($_POST['_csrf'] ?? null);

        try {
            (new BackupService())->delete(
                (int)($_POST['id'] ?? 0)
            );

            $_SESSION['success'] =
                'Sauvegarde supprimée.';
        } catch (Throwable $error) {
            $_SESSION['error'] =
                'Échec : ' . $error->getMessage();
        }

        $this->redirect('/studio/sauvegardes');
    }

    public function developerExport(): void
    {
        Auth::requireLogin();
        Permission::require('backups.download');
        Permission::requireSuperAdmin();
        Auth::requireRecentAuthentication();
        Csrf::verify($_POST['_csrf'] ?? null);

        $file = null;
        try {
            $file = (new BackupService())->createDeveloperExport((int)Auth::id());
            header('Content-Type: application/zip');
            header('Content-Disposition: attachment; filename="' . basename($file) . '"');
            header('Content-Length: ' . filesize($file));
            header('X-Content-Type-Options: nosniff');
            header('Cache-Control: no-store, private');
            header('Pragma: no-cache');
            readfile($file);
        } catch (Throwable $error) {
            $_SESSION['error'] = 'Export développeur refusé : ' . $error->getMessage();
            $this->redirect('/studio/sauvegardes');
            return;
        } finally {
            if (is_string($file) && is_file($file)) {
                @unlink($file);
            }
        }
        exit;
    }

    public function download(): void
    {
        Auth::requireLogin();
        Permission::require('backups.download');
        Permission::requireSuperAdmin();
        Auth::requireRecentAuthentication();

        $job = BackupJob::find(
            (int)($_GET['id'] ?? 0)
        );

        if (
            !$job ||
            !is_file((string)$job['chemin'])
        ) {
            http_response_code(404);
            exit('Fichier introuvable.');
        }

        $file = (string)$job['chemin'];
        $backupRoot = realpath(BASE_PATH . '/storage/backups');
        $resolvedFile = realpath($file);
        if ($backupRoot === false || $resolvedFile === false
            || !str_starts_with(str_replace('\\', '/', $resolvedFile) . '/', rtrim(str_replace('\\', '/', $backupRoot), '/') . '/')) {
            http_response_code(404);
            exit('Fichier introuvable.');
        }
        $file = $resolvedFile;
        $lower = strtolower($file);

        if (str_ends_with($lower, '.axiombak')) {
            $contentType = 'application/octet-stream';
        } elseif (str_ends_with($lower, '.zip')) {
            $contentType = 'application/zip';
        } elseif (
            str_ends_with($lower, '.tar.gz') ||
            str_ends_with($lower, '.tgz')
        ) {
            $contentType = 'application/gzip';
        } else {
            $contentType =
                'application/octet-stream';
        }

        header('Content-Type: ' . $contentType);
        header(
            'Content-Disposition: attachment; filename="'
            . basename($file)
            . '"'
        );
        header(
            'Content-Length: ' . filesize($file)
        );
        header('X-Content-Type-Options: nosniff');
        header('Cache-Control: no-store, private');
        header('Pragma: no-cache');

        readfile($file);
        exit;
    }
}
