<?php

namespace App\Entity;

use App\Repository\ActivityLogRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

/**
 * Journal d'audit : trace qui a fait quoi et quand sur les actions sensibles
 * (changements de statut et de concessions d'un scan, suppressions, archivage,
 * imports Paramètres, gestion des utilisateurs). Consultable sur /journal
 * (ADMIN + AUDIT). Les entrées survivent à la suppression du scan : on
 * dénormalise l'id et le libellé plutôt que de poser une FK.
 */
#[ORM\Entity(repositoryClass: ActivityLogRepository::class)]
#[ORM\Table(name: 'activity_logs')]
#[ORM\Index(name: 'idx_activity_created', columns: ['created_at'])]
#[ORM\Index(name: 'idx_activity_scan', columns: ['scan_id'])]
class ActivityLog
{
    // Actions sur les scans
    public const SCAN_CREATE = 'scan.create';
    public const SCAN_STATUS = 'scan.status';
    public const SCAN_RENAME = 'scan.rename';
    public const SCAN_CONCESSIONS = 'scan.concessions';
    public const SCAN_ARCHIVE = 'scan.archive';
    public const SCAN_UNARCHIVE = 'scan.unarchive';
    public const SCAN_DELETE = 'scan.delete';
    public const SCAN_DELETE_ALL = 'scan.delete_all';
    // Paramètres
    public const PARAM_CONCESSIONS_IMPORT = 'param.concessions_import';
    public const PARAM_STOCK_IMPORT = 'param.stock_import';
    public const PARAM_STOCK_RESET = 'param.stock_reset';
    // Gestion des utilisateurs
    public const USER_VALIDATE = 'user.validate';
    public const USER_UPDATE = 'user.update';
    public const USER_REFUSE = 'user.refuse';
    public const USER_DELETE = 'user.delete';

    public const LABELS = [
        self::SCAN_CREATE => 'Création du scan',
        self::SCAN_STATUS => 'Changement de statut',
        self::SCAN_RENAME => 'Renommage de l\'inventaire',
        self::SCAN_CONCESSIONS => 'Modification des concessions',
        self::SCAN_ARCHIVE => 'Archivage',
        self::SCAN_UNARCHIVE => 'Désarchivage',
        self::SCAN_DELETE => 'Suppression du scan',
        self::SCAN_DELETE_ALL => 'Suppression des scans personnels',
        self::PARAM_CONCESSIONS_IMPORT => 'Import du référentiel concessions',
        self::PARAM_STOCK_IMPORT => 'Import de la photo du stock',
        self::PARAM_STOCK_RESET => 'Suppression de la photo du stock',
        self::USER_VALIDATE => 'Validation d\'un utilisateur',
        self::USER_UPDATE => 'Modification d\'un utilisateur',
        self::USER_REFUSE => 'Refus d\'une demande d\'accès',
        self::USER_DELETE => 'Suppression d\'un utilisateur',
    ];

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
    private \DateTimeImmutable $createdAt;

    /** Auteur de l'action (email du compte connecté). */
    #[ORM\Column(length: 180)]
    private string $userEmail;

    #[ORM\Column(length: 48)]
    private string $action;

    /** Scan concerné, le cas échéant (pas de FK : l'entrée survit à la suppression). */
    #[ORM\Column(length: 36, nullable: true)]
    private ?string $scanId;

    /** Libellé du scan au moment de l'action (lisible même après suppression). */
    #[ORM\Column(length: 255, nullable: true)]
    private ?string $scanLabel;

    /** @var array<string, mixed> Détails propres à l'action (avant/après, cible, volumes…). */
    #[ORM\Column(type: Types::JSON)]
    private array $details;

    /** @param array<string, mixed> $details */
    public function __construct(string $userEmail, string $action, ?string $scanId, ?string $scanLabel, array $details)
    {
        $this->createdAt = new \DateTimeImmutable();
        $this->userEmail = mb_substr($userEmail, 0, 180);
        $this->action = mb_substr($action, 0, 48);
        $this->scanId = $scanId;
        $this->scanLabel = null !== $scanLabel ? mb_substr($scanLabel, 0, 255) : null;
        $this->details = $details;
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getCreatedAt(): \DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function getUserEmail(): string
    {
        return $this->userEmail;
    }

    public function getAction(): string
    {
        return $this->action;
    }

    public function getActionLabel(): string
    {
        return self::LABELS[$this->action] ?? $this->action;
    }

    public function getScanId(): ?string
    {
        return $this->scanId;
    }

    public function getScanLabel(): ?string
    {
        return $this->scanLabel;
    }

    /** @return array<string, mixed> */
    public function getDetails(): array
    {
        return $this->details;
    }
}
