<?php
declare(strict_types=1);

namespace App\Core;

use App\Services\SecurityEventMonitor;

final class PortalSimulation
{
    private const PROFESSOR_KEY = 'axiom_simulated_professor_id';
    private const CLIENT_KEY = 'axiom_simulated_client_id';
    private const STARTED_AT_KEY = 'axiom_simulation_started_at';

    public static function isAvailable(): bool
    {
        return Permission::isSuperAdmin();
    }

    public static function isActive(): bool
    {
        return self::professorId() !== null || self::clientId() !== null;
    }

    /** @return array{type:string,id:int,label:string,started_at:int}|null */
    public static function context(): ?array
    {
        if (($id = self::professorId()) !== null) {
            $stmt = Database::connection()->prepare(
                "SELECT CONCAT(COALESCE(prenom,''),' ',COALESCE(nom,'')) FROM professeurs
                 WHERE id=:id AND organisation_id=:organisation_id AND actif=1 AND deleted_at IS NULL"
            );
            $stmt->execute(['id'=>$id, 'organisation_id'=>self::organisationId()]);
            return ['type'=>'professeur','id'=>$id,'label'=>trim((string)$stmt->fetchColumn()),'started_at'=>(int)($_SESSION[self::STARTED_AT_KEY] ?? 0)];
        }
        if (($id = self::clientId()) !== null) {
            $stmt = Database::connection()->prepare(
                "SELECT CONCAT(COALESCE(prenom,''),' ',COALESCE(nom,'')) FROM clients
                 WHERE id=:id AND organisation_id=:organisation_id AND statut='actif' AND deleted_at IS NULL"
            );
            $stmt->execute(['id'=>$id, 'organisation_id'=>self::organisationId()]);
            return ['type'=>'famille','id'=>$id,'label'=>trim((string)$stmt->fetchColumn()),'started_at'=>(int)($_SESSION[self::STARTED_AT_KEY] ?? 0)];
        }
        return null;
    }

    public static function professorId(): ?int
    {
        return self::validatedId(self::PROFESSOR_KEY,
            "SELECT id FROM professeurs WHERE id=:id AND organisation_id=:organisation_id AND actif=1 AND deleted_at IS NULL");
    }

    public static function clientId(): ?int
    {
        return self::validatedId(self::CLIENT_KEY,
            "SELECT id FROM clients WHERE id=:id AND organisation_id=:organisation_id AND statut='actif' AND deleted_at IS NULL");
    }

    public static function selectProfessor(int $id): bool
    {
        if (!self::isAvailable()) return false;
        self::clear(false);
        $_SESSION[self::PROFESSOR_KEY] = $id;
        $_SESSION[self::STARTED_AT_KEY] = time();
        if (self::professorId() === null) { self::clear(false); return false; }
        self::logStart('professeur', $id);
        return true;
    }

    public static function selectClient(int $id): bool
    {
        if (!self::isAvailable()) return false;
        self::clear(false);
        $_SESSION[self::CLIENT_KEY] = $id;
        $_SESSION[self::STARTED_AT_KEY] = time();
        if (self::clientId() === null) { self::clear(false); return false; }
        self::logStart('famille', $id);
        return true;
    }

    public static function clear(bool $audit = true): void
    {
        $context = $audit ? self::context() : null;
        unset($_SESSION[self::PROFESSOR_KEY], $_SESSION[self::CLIENT_KEY], $_SESSION[self::STARTED_AT_KEY]);
        if ($context !== null) {
            SecurityEventMonitor::record('impersonation.stopped', 'info', [
                'impersonation_type'=>$context['type'],
                'impersonated_id'=>$context['id'],
                'duration_seconds'=>max(0, time() - $context['started_at']),
            ]);
        }
    }

    private static function logStart(string $type, int $id): void
    {
        SecurityEventMonitor::record('impersonation.started', 'info', [
            'impersonation_type'=>$type,
            'impersonated_id'=>$id,
            'authenticated_user_id'=>(int)(Auth::id() ?? 0),
        ]);
    }

    private static function validatedId(string $key, string $sql): ?int
    {
        if (!self::isAvailable()) return null;
        $id = (int)($_SESSION[$key] ?? 0);
        if ($id <= 0) return null;
        $stmt = Database::connection()->prepare($sql);
        $stmt->execute(['id'=>$id, 'organisation_id'=>self::organisationId()]);
        $validated = (int)$stmt->fetchColumn();
        if ($validated <= 0) unset($_SESSION[$key]);
        return $validated > 0 ? $validated : null;
    }

    private static function organisationId(): int
    {
        return (int)(Auth::user()['organisation_id'] ?? 1);
    }
}
