<?php
namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Database;
use App\Core\ModuleManager;
use App\Core\Notifier;
use PDO;

class ModulesController extends Controller
{
    private const INSTALLATION_SECURITY_CODE = '0780';

    private PDO $pdo;

    public function __construct()
    {
        $this->pdo = Database::pdo();
        ModuleManager::ensureSchema($this->pdo);
    }

    public function index(): void
    {
        if (!Auth::check()) { $this->redirect('/login'); }
        Auth::requireRole(['admin']);

        $this->view('settings/modules', [
            'title' => 'Gestion des modules',
            'modules' => ModuleManager::all($this->pdo),
            'action_status' => trim((string)($_GET['action_status'] ?? '')),
            'action_module' => trim((string)($_GET['module'] ?? '')),
        ]);
    }

    public function install(): void
    {
        $this->handleMutation('install');
    }

    public function enable(): void
    {
        $this->handleMutation('enable');
    }

    public function disable(): void
    {
        $this->handleMutation('disable');
    }

    public function uninstall(): void
    {
        $this->handleMutation('uninstall');
    }

    private function handleMutation(string $action): void
    {
        if (!Auth::check()) { $this->redirect('/login'); }
        Auth::requireRole(['admin']);
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            $this->redirect('/settings/modules');
            return;
        }

        $moduleKey = trim((string)($_POST['module_key'] ?? ''));

        if ($action === 'install') {
            $providedCode = trim((string)($_POST['installation_code'] ?? ''));
            if ($providedCode !== self::INSTALLATION_SECURITY_CODE) {
                $this->notifyModuleInstallFraudAttempt($moduleKey, Auth::user() ?? []);
                $this->redirect('/settings/modules?action_status=' . rawurlencode('fraud_attempt') . '&module=' . rawurlencode($moduleKey));
                return;
            }
        }

        switch ($action) {
            case 'install':
                ModuleManager::install($this->pdo, $moduleKey);
                break;
            case 'enable':
                ModuleManager::setEnabled($this->pdo, $moduleKey, true);
                break;
            case 'disable':
                ModuleManager::setEnabled($this->pdo, $moduleKey, false);
                break;
            case 'uninstall':
                ModuleManager::uninstall($this->pdo, $moduleKey);
                break;
        }

        $this->redirect('/settings/modules?action_status=' . rawurlencode($action) . '&module=' . rawurlencode($moduleKey));
    }

    private function notifyModuleInstallFraudAttempt(string $moduleKey, array $currentUser): void
    {
        $recipientIds = $this->resolveModuleSecurityRecipientIds();
        if ($recipientIds === []) {
            return;
        }

        $userName = trim((string)($currentUser['name'] ?? 'Utilisateur inconnu'));
        $userEmail = trim((string)($currentUser['email'] ?? 'email inconnu'));
        $userId = (int)($currentUser['id'] ?? 0);
        $ip = trim((string)($_SERVER['REMOTE_ADDR'] ?? 'IP inconnue'));
        $moduleLabel = $moduleKey !== '' ? $moduleKey : 'module inconnu';

        Notifier::notifyUsers(
            $this->pdo,
            $recipientIds,
            'Alerte sécurité modules',
            sprintf(
                'Tentative de fraude détectée sur l\'installation du module %s par %s (%s, ID %d) depuis %s.',
                $moduleLabel,
                $userName,
                $userEmail,
                $userId,
                $ip
            ),
            route_url('/settings/modules')
        );
    }

    private function resolveModuleSecurityRecipientIds(): array
    {
        $statement = $this->pdo->query("SELECT id FROM users WHERE active = 1 AND role_key IN ('admin','manager')");
        return array_values(array_filter(array_map('intval', $statement ? ($statement->fetchAll(PDO::FETCH_COLUMN) ?: []) : [])));
    }
}