<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Controller;
use App\Core\Session;
use App\Services\MaintenanceService;
use App\Services\SystemMaintenanceService;
use App\Core\Version;

final class MaintenanceController extends Controller
{
    public function index(): void
    {
        $service = new MaintenanceService();

        $this->view('maintenance/index', [
            'title' => 'Maintenance',
            'checks' => $service->runChecks(),
            'summary' => $service->summary(),
            'systemInformation' => $service->getSystemInformation(),
            'databaseInformation' => $service->getDatabaseInformation(),
            'statistics' => $service->getStatistics(),
            'backups' => $service->listDatabaseBackups(),
            'backupStatus' => $service->getBackupStatus(),
            'backupMetrics' => $service->getBackupMetrics(),
            'cards' => [
                [
                    'title' => 'Sauvegarde SQL',
                    'icon' => 'bi-database-check',
                    'url' => 'index.php?page=maintenance_backup',
                    'method' => 'post',
                    'confirmation' => 'Créer une sauvegarde rapide de la base de données ?',
                    'text' => 'Base uniquement — idéale avant une opération sensible',
                ],
                [
                    'title' => 'Sauvegarde complète',
                    'icon' => 'bi-file-earmark-zip',
                    'url' => 'index.php?page=maintenance_backup_complete',
                    'method' => 'post',
                    'confirmation' => 'Créer une sauvegarde complète de la base et des fichiers ?',
                    'text' => 'Base, documents, imports, téléversements et ressources',
                ],
                [
                    'title' => 'Restauration',
                    'icon' => 'bi-arrow-counterclockwise',
                    'url' => '#gestionnaire-sauvegardes',
                    'text' => 'Restaurer automatiquement une sauvegarde SQL ou ZIP',
                ],
                [
                    'title' => 'Nettoyage',
                    'icon' => 'bi-broom',
                    'url' => 'index.php?page=maintenance_cleanup',
                    'text' => 'Vider le cache et les fichiers temporaires',
                ],
                [
                    'title' => 'Journaux',
                    'icon' => 'bi-journal-text',
                    'url' => 'index.php?page=maintenance_logs',
                    'text' => 'Consulter les journaux système',
                ],
                [
                    'title' => 'Informations système',
                    'icon' => 'bi-pc-display',
                    'url' => 'index.php?page=maintenance_system',
                    'text' => 'PHP, MySQL, version et statistiques',
                ],
                [
                    'title' => 'Version',
                    'icon' => 'bi-info-circle',
                    'url' => 'index.php?page=maintenance_version',
                    'text' => 'Informations sur Darlink ERP Phoenix',
                ],
            ],
        ]);
    }

    public function backup(): void
    {
        try {
            $backup = (new MaintenanceService())->createDatabaseBackup();
            $this->flashBackupSuccess('Sauvegarde SQL', $backup);
        } catch (\Throwable $exception) {
            Session::flash('error', 'Échec de la sauvegarde SQL : ' . $exception->getMessage());
        }
        $this->redirect('maintenance');
    }

    public function completeBackup(): void
    {
        try {
            $backup = (new MaintenanceService())->createCompleteBackup();
            $this->flashBackupSuccess('Sauvegarde complète', $backup);
        } catch (\Throwable $exception) {
            Session::flash('error', 'Échec de la sauvegarde complète : ' . $exception->getMessage());
        }
        $this->redirect('maintenance');
    }

    public function downloadBackup(): void
    {
        try {
            $filePath = (new MaintenanceService())->getDatabaseBackupPath((string) ($_GET['file'] ?? ''));
            if (headers_sent()) {
                throw new \RuntimeException('Le téléchargement ne peut pas démarrer car des données ont déjà été envoyées.');
            }
            $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
            header('Content-Type: ' . ($extension === 'zip' ? 'application/zip' : 'application/sql'));
            header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
            header('Content-Length: ' . filesize($filePath));
            header('X-Content-Type-Options: nosniff');
            readfile($filePath);
            exit;
        } catch (\Throwable $exception) {
            Session::flash('error', 'Téléchargement impossible : ' . $exception->getMessage());
            $this->redirect('maintenance');
        }
    }

    public function deleteBackup(): void
    {
        try {
            (new MaintenanceService())->deleteDatabaseBackup((string) ($_POST['file'] ?? ''));
            Session::flash('success', 'Sauvegarde supprimée avec succès.');
        } catch (\Throwable $exception) {
            Session::flash('error', 'Suppression impossible : ' . $exception->getMessage());
        }
        $this->redirect('maintenance');
    }

    public function restoreBackup(): void
    {
        try {
            $fileName = trim((string) ($_POST['file'] ?? ''));
            if ($fileName === '') {
                throw new \InvalidArgumentException('Aucune sauvegarde n’a été sélectionnée.');
            }
            if (trim((string) ($_POST['confirmation'] ?? '')) !== 'RESTAURER') {
                throw new \InvalidArgumentException('La confirmation de restauration est incorrecte.');
            }

            $result = (new MaintenanceService())->restoreDatabaseBackup($fileName);
            $message = 'Restauration terminée depuis ' . $result['restored_file']
                . '. ' . $result['executed_statements'] . ' instruction(s) SQL exécutée(s).';
            if ((int) ($result['restored_files'] ?? 0) > 0) {
                $message .= ' ' . (int) $result['restored_files'] . ' fichier(s) restauré(s).';
            }
            $message .= ' Point de sécurité créé : ' . $result['safety_backup'] . '.';
            Session::flash('success', $message);
        } catch (\Throwable $exception) {
            Session::flash('error', 'Restauration impossible : ' . $exception->getMessage());
        }
        $this->redirect('maintenance');
    }

    public function cleanup(): void
    {
        $service = new SystemMaintenanceService();
        $this->view('maintenance/cleanup', [
            'title' => 'Nettoyage',
            'groups' => $service->cleanupAnalysis(),
        ]);
    }

    public function runCleanup(): void
    {
        try {
            $selected = array_values(array_filter((array) ($_POST['targets'] ?? []), 'is_string'));
            if ($selected === []) {
                throw new \InvalidArgumentException('Sélectionnez au moins une catégorie à nettoyer.');
            }
            if ((string) ($_POST['confirmation'] ?? '') !== 'NETTOYER') {
                throw new \InvalidArgumentException('La confirmation de nettoyage est incorrecte.');
            }
            $result = (new SystemMaintenanceService())->cleanup($selected);
            Session::flash('success', sprintf('%d fichier(s) supprimé(s), %s libéré(s).', $result['deleted'], $this->formatBytes((int) $result['freed'])));
        } catch (\Throwable $exception) {
            Session::flash('error', 'Nettoyage impossible : ' . $exception->getMessage());
        }
        $this->redirect('maintenance_cleanup');
    }

    public function logs(): void
    {
        $service = new SystemMaintenanceService();
        $selectedId = trim((string) ($_GET['log'] ?? ''));
        $selectedLog = null;
        if ($selectedId !== '') {
            try {
                $selectedLog = $service->readLog($selectedId, trim((string) ($_GET['search'] ?? '')), trim((string) ($_GET['level'] ?? '')));
            } catch (\Throwable $exception) {
                Session::flash('error', $exception->getMessage());
            }
        }
        $this->view('maintenance/logs', ['title' => 'Journaux', 'logs' => $service->listLogs(), 'selectedLog' => $selectedLog, 'selectedId' => $selectedId]);
    }

    public function clearLog(): void
    {
        try {
            if ((string) ($_POST['confirmation'] ?? '') !== 'VIDER') {
                throw new \InvalidArgumentException('La confirmation est incorrecte.');
            }
            (new SystemMaintenanceService())->clearLog((string) ($_POST['log'] ?? ''));
            Session::flash('success', 'Journal vidé avec succès.');
        } catch (\Throwable $exception) {
            Session::flash('error', 'Impossible de vider le journal : ' . $exception->getMessage());
        }
        $this->redirect('maintenance_logs');
    }

    public function downloadLog(): void
    {
        try {
            $path = (new SystemMaintenanceService())->logPath((string) ($_GET['log'] ?? ''));
            header('Content-Type: text/plain; charset=UTF-8');
            header('Content-Disposition: attachment; filename="' . basename($path) . '"');
            header('Content-Length: ' . filesize($path));
            header('X-Robots-Tag: noindex, noarchive', true);
            readfile($path);
            exit;
        } catch (\Throwable $exception) {
            Session::flash('error', 'Téléchargement impossible : ' . $exception->getMessage());
            $this->redirect('maintenance_logs');
        }
    }

    public function system(): void
    {
        $service = new SystemMaintenanceService();
        $this->view('maintenance/system', [
            'title' => 'Informations système',
            'information' => $service->systemInformation(),
        ]);
    }

    public function version(): void
    {
        $this->view('maintenance/version', [
            'title' => 'Version',
            'application' => Version::APPLICATION,
            'version' => Version::number(),
            'build' => Version::build(),
            'edition' => Version::edition(),
            'schema' => Version::schema(),
        ]);
    }

    private function formatBytes(int $bytes): string
    {
        if ($bytes >= 1073741824) { return number_format($bytes / 1073741824, 2, ',', ' ') . ' Go'; }
        if ($bytes >= 1048576) { return number_format($bytes / 1048576, 2, ',', ' ') . ' Mo'; }
        if ($bytes >= 1024) { return number_format($bytes / 1024, 2, ',', ' ') . ' Ko'; }
        return $bytes . ' o';
    }

    private function flashBackupSuccess(string $label, array $backup): void
    {
        $sizeMb = (float) ($backup['file_size'] ?? 0) / 1024 / 1024;
        $message = $label . ' créée avec succès : ' . ($backup['file_name'] ?? '')
            . ' (' . number_format($sizeMb, 2, ',', ' ') . ' Mo';
        if ((int) ($backup['file_count'] ?? 0) > 1) {
            $message .= ', ' . (int) $backup['file_count'] . ' fichier(s)';
        }
        Session::flash('success', $message . ').');
    }
}
