<?php

declare(strict_types=1);

namespace App\Domain\Audit;

/**
 * Stable string constants for `audit_log.action`. The value is the
 * "<entity>.<verb>" pair surfaced in the API and the UI's filter
 * dropdown. Kept as constants (not an enum) so adding a new action
 * is a one-line patch and so the values can flow through DBAL without
 * the enum casting boilerplate.
 *
 * `entityType` for each action is the prefix before the dot (e.g.
 * `reporter.created` -> entity_type=reporter); the helper below maps
 * automatically.
 */
final class AuditAction
{
    public const REPORTER_CREATED = 'reporter.created';
    public const REPORTER_UPDATED = 'reporter.updated';
    public const REPORTER_DELETED = 'reporter.deleted';
    // SEC_REVIEW F41: dedicated alertable signal for the per-reporter
    // `audit_enabled` flag flipping. The standard `reporter.updated`
    // row continues to carry the full field diff; this row exists so
    // SIEM tooling can match a toggle of audit emission with a flat
    // `action = 'reporter.audit_toggled'` rule rather than walking
    // into the metadata `changes` blob.
    public const REPORTER_AUDIT_TOGGLED = 'reporter.audit_toggled';

    public const CONSUMER_CREATED = 'consumer.created';
    public const CONSUMER_UPDATED = 'consumer.updated';
    public const CONSUMER_DELETED = 'consumer.deleted';
    // SEC_REVIEW F41: same as the reporter sibling above.
    public const CONSUMER_AUDIT_TOGGLED = 'consumer.audit_toggled';

    public const TOKEN_CREATED = 'token.created';
    public const TOKEN_REVOKED = 'token.revoked';
    public const TOKEN_DELETED = 'token.deleted';

    public const POLICY_CREATED = 'policy.created';
    public const POLICY_UPDATED = 'policy.updated';
    public const POLICY_DELETED = 'policy.deleted';

    public const CATEGORY_CREATED = 'category.created';
    public const CATEGORY_UPDATED = 'category.updated';
    public const CATEGORY_DELETED = 'category.deleted';

    public const MANUAL_BLOCK_CREATED = 'manual_block.created';
    public const MANUAL_BLOCK_DELETED = 'manual_block.deleted';

    public const ALLOWLIST_CREATED = 'allowlist.created';
    public const ALLOWLIST_DELETED = 'allowlist.deleted';

    public const USER_CREATED = 'user.created';
    public const USER_ROLE_CHANGED = 'user.role_changed';
    public const USER_DISABLED = 'user.disabled';
    public const USER_ENABLED = 'user.enabled';
    // SEC_REVIEW F17: read-side audit. The only read action we record;
    // emitted from `GET /api/v1/auth/users/{id}` so iterative
    // enumeration of the users table by a service-token holder leaves
    // a per-id trail that SOC tooling can alert on.
    public const USER_FETCHED = 'user.fetched';

    public const OIDC_ROLE_MAPPING_CREATED = 'oidc_role_mapping.created';
    public const OIDC_ROLE_MAPPING_DELETED = 'oidc_role_mapping.deleted';

    public const JOB_TRIGGERED = 'job.triggered';

    public const MAINTENANCE_PURGED = 'maintenance.purged';
    public const MAINTENANCE_SEEDED = 'maintenance.seeded';

    public const REPORT_RECEIVED = 'report.received';
    public const BLOCKLIST_REQUESTED = 'blocklist.requested';

    public const APP_SETTINGS_UPDATED = 'app_settings.updated';

    public static function entityTypeFor(string $action): string
    {
        $dot = strpos($action, '.');

        return $dot === false ? $action : substr($action, 0, $dot);
    }
}
