# Event Replay & Time Travel System

Comprehensive event replay and time travel debugging capabilities for Event Sourcing in the Custom PHP Framework.

## Übersicht

Das Event Replay & Time Travel System ermöglicht:
- **Event Replay**: Wiederholung von Events mit verschiedenen Strategien
- **Time Travel Debugging**: Rekonstruktion des Aggregate-Zustands zu jedem beliebigen Zeitpunkt
- **Projection Rebuilding**: Neuaufbau von Projektionen aus Event-Historie
- **Event History Visualization**: Analyse und Visualisierung von Event-Streams
- **CLI Commands**: Mächtige Kommandozeilen-Tools für Debugging und Wartung

## Architektur

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  EventReplayer  │───▶│ Replay Strategy │───▶│   Event Store   │
│                 │    │                 │    │                 │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                      │                       │
   Callback Support      Strategy Selection        Event Loading
         │                      │                       │
         ▼                      ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ TimeTravelDebug │    │ ProjectionRebld │    │ HistoryVisual.  │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

## Kern-Komponenten

### 1. Event Replayer

**EventReplayer** - Haupt-Replay-Engine:

```php
final readonly class EventReplayer
{
    public function __construct(
        private EventStore $eventStore
    ) {}

    // Alle Events eines Aggregates mit Strategy replaying
    public function replayAggregate(
        AggregateId $aggregateId,
        ReplayStrategy $strategy
    ): array;

    // Replay mit Callback für jedes Event
    public function replayWithCallback(
        AggregateId $aggregateId,
        ReplayStrategy $strategy,
        callable $callback
    ): int;

    // Event-Stream als Array zurückgeben
    public function getEventStream(
        AggregateId $aggregateId,
        ReplayStrategy $strategy
    ): array;
}
```

### 2. Replay Strategies

**FullReplayStrategy** - Alle Events von Anfang an:

```php
$strategy = new FullReplayStrategy();

$events = $replayer->replayAggregate($aggregateId, $strategy);
// Replayed alle Events des Aggregates
```

**FromVersionReplayStrategy** - Ab spezifischer Version:

```php
$strategy = new FromVersionReplayStrategy(fromVersion: 10);

$events = $replayer->replayAggregate($aggregateId, $strategy);
// Nur Events ab Version 10
```

**TimeRangeReplayStrategy** - Zeitbasierte Replay mit Factory Methods:

```php
// Vordefinierte Zeiträume
$strategy = TimeRangeReplayStrategy::today();
$strategy = TimeRangeReplayStrategy::yesterday();
$strategy = TimeRangeReplayStrategy::lastHours(6);
$strategy = TimeRangeReplayStrategy::lastDays(7);

// Custom Zeitraum
$strategy = new TimeRangeReplayStrategy(
    startTime: Timestamp::fromString('2024-01-01 00:00:00'),
    endTime: Timestamp::now()
);

$events = $replayer->replayAggregate($aggregateId, $strategy);
```

**EventTypeReplayStrategy** - Nur spezifische Event-Typen:

```php
// Einzelner Event-Typ
$strategy = EventTypeReplayStrategy::forType(UserRegisteredEvent::class);

// Multiple Event-Typen
$strategy = new EventTypeReplayStrategy([
    UserRegisteredEvent::class,
    UserActivatedEvent::class,
    UserVerifiedEvent::class
]);

$events = $replayer->replayAggregate($aggregateId, $strategy);
```

**VersionRangeReplayStrategy** - Versions-Bereich:

```php
$strategy = new VersionRangeReplayStrategy(
    fromVersion: 5,
    toVersion: 15
);

$events = $replayer->replayAggregate($aggregateId, $strategy);
// Events von Version 5 bis 15
```

### 3. Time Travel Debugger

**TimeTravelDebugger** - Aggregate-Zustand zu jedem Zeitpunkt:

```php
final readonly class TimeTravelDebugger
{
    // Zustand zu bestimmter Zeit rekonstruieren
    public function getStateAtTime(
        AggregateId $aggregateId,
        Timestamp $targetTime,
        callable $aggregateFactory
    ): ?AggregateRoot;

    // Zustand bei spezifischer Version
    public function getStateAtVersion(
        AggregateId $aggregateId,
        int $targetVersion,
        callable $aggregateFactory
    ): ?AggregateRoot;

    // Zustandsänderungen zwischen Zeitpunkten
    public function getStateChanges(
        AggregateId $aggregateId,
        Timestamp $startTime,
        Timestamp $endTime,
        callable $aggregateFactory
    ): array; // ['before' => ..., 'after' => ..., 'events' => ...]

    // Finde wann Bedingung erfüllt wurde
    public function findWhenConditionBecameTrue(
        AggregateId $aggregateId,
        callable $aggregateFactory,
        callable $condition
    ): ?array; // ['version' => ..., 'timestamp' => ..., 'state' => ...]
}
```

**Verwendung - Zustand zu bestimmter Zeit**:

```php
$debugger = $container->get(TimeTravelDebugger::class);

// Aggregate Factory definieren
$aggregateFactory = fn() => new Order(new OrderId('order-123'));

// Zustand gestern um 14:00 rekonstruieren
$targetTime = Timestamp::fromString('2024-01-15 14:00:00');
$historicState = $debugger->getStateAtTime(
    aggregateId: new OrderId('order-123'),
    targetTime: $targetTime,
    aggregateFactory: $aggregateFactory
);

if ($historicState) {
    echo "Order Status damals: " . $historicState->getStatus();
    echo "Order Total damals: " . $historicState->getTotal()->toDecimal();
}
```

**Verwendung - Zustandsänderungen analysieren**:

```php
// Was hat sich zwischen gestern und heute geändert?
$changes = $debugger->getStateChanges(
    aggregateId: new OrderId('order-123'),
    startTime: Timestamp::yesterday(),
    endTime: Timestamp::now(),
    aggregateFactory: fn() => new Order(new OrderId('order-123'))
);

echo "Zustand gestern: " . json_encode($changes['before']);
echo "Zustand heute: " . json_encode($changes['after']);
echo "Events dazwischen: " . count($changes['events']);
```

**Verwendung - Finde wann Bedingung erfüllt**:

```php
// Wann wurde die Order komplett?
$result = $debugger->findWhenConditionBecameTrue(
    aggregateId: new OrderId('order-123'),
    aggregateFactory: fn() => new Order(new OrderId('order-123')),
    condition: fn(Order $order) => $order->isCompleted()
);

if ($result) {
    echo "Order wurde komplett bei Version: {$result['version']}";
    echo "Timestamp: {$result['timestamp']->format('Y-m-d H:i:s')}";
}
```

### 4. Projection Rebuilder

**ProjectionRebuilder** - Projektionen aus Event-Historie neu aufbauen:

```php
final readonly class ProjectionRebuilder
{
    // Einzelne Projektion neu aufbauen
    public function rebuildProjection(
        string $projectionName,
        ReplayStrategy $strategy = null
    ): array;

    // Projektion für spezifisches Aggregate
    public function rebuildProjectionForAggregate(
        ProjectionInterface $projection,
        AggregateId $aggregateId,
        ReplayStrategy $strategy = null
    ): int;

    // Alle Projektionen neu aufbauen
    public function rebuildAllProjections(
        ReplayStrategy $strategy = null
    ): array;
}
```

**Verwendung - Projektion neu aufbauen**:

```php
$rebuilder = $container->get(ProjectionRebuilder::class);

// Einzelne Projektion komplett neu aufbauen
$result = $rebuilder->rebuildProjection('user_statistics');

echo "Strategy: {$result['strategy']}";
echo "Status: {$result['status']}";
echo "Last Version: {$result['last_version']}";
```

**Verwendung - Mit Replay Strategy**:

```php
// Nur letzte 7 Tage neu aufbauen
$strategy = TimeRangeReplayStrategy::lastDays(7);
$result = $rebuilder->rebuildProjection('user_statistics', $strategy);

// Nur ab Version 100
$strategy = new FromVersionReplayStrategy(100);
$result = $rebuilder->rebuildProjection('order_totals', $strategy);
```

**Verwendung - Alle Projektionen**:

```php
$results = $rebuilder->rebuildAllProjections();

foreach ($results as $result) {
    echo "Projection: {$result->projectionName}";
    echo "Status: {$result->status->value}";
    echo "Events Processed: {$result->eventsProcessed}";
}
```

### 5. Event History Visualizer

**EventHistoryVisualizer** - Event-Stream-Analyse und Visualisierung:

```php
final readonly class EventHistoryVisualizer
{
    // Timeline-Visualisierung generieren
    public function generateTimeline(AggregateId $aggregateId): array;

    // Event-Typ-Verteilung
    public function getEventTypeDistribution(AggregateId $aggregateId): array;

    // Event-Frequenz pro Tag
    public function getEventFrequencyByDay(AggregateId $aggregateId): array;

    // Event-Frequenz pro Stunde
    public function getEventFrequencyByHour(AggregateId $aggregateId): array;

    // Stream-Zusammenfassung
    public function getStreamSummary(AggregateId $aggregateId): array;

    // Zeiträume vergleichen
    public function compareTimePeriods(
        AggregateId $aggregateId,
        array $period1,
        array $period2
    ): array;
}
```

**Verwendung - Timeline generieren**:

```php
$visualizer = $container->get(EventHistoryVisualizer::class);

$timeline = $visualizer->generateTimeline(new OrderId('order-123'));

// Timeline-Daten
foreach ($timeline['timeline'] as $entry) {
    echo "v{$entry['version']} - {$entry['timestamp']} - {$entry['event_type']}\n";
}

// Statistiken
$stats = $timeline['statistics'];
echo "Total Events: {$stats['total_events']}";
echo "Time Span: {$stats['time_span_hours']} hours";
echo "Unique Event Types: {$stats['unique_event_types']}";
```

**Verwendung - Event-Typ-Verteilung**:

```php
$distribution = $visualizer->getEventTypeDistribution(new OrderId('order-123'));

foreach ($distribution as $eventType => $count) {
    echo "{$eventType}: {$count} occurrences\n";
}
// Output:
// OrderPlacedEvent: 1
// OrderItemAddedEvent: 5
// OrderCompletedEvent: 1
```

**Verwendung - Stream-Zusammenfassung**:

```php
$summary = $visualizer->getStreamSummary(new OrderId('order-123'));

echo "Aggregate ID: {$summary['aggregate_id']}";
echo "Total Events: {$summary['total_events']}";
echo "First Event: {$summary['first_event']['type']} @ {$summary['first_event']['timestamp']}";
echo "Last Event: {$summary['last_event']['type']} @ {$summary['last_event']['timestamp']}";
echo "Time Span: {$summary['time_span']['duration_hours']} hours";
```

**Verwendung - Zeiträume vergleichen**:

```php
$comparison = $visualizer->compareTimePeriods(
    aggregateId: new OrderId('order-123'),
    period1: [
        'start' => Timestamp::fromString('2024-01-01 00:00:00'),
        'end' => Timestamp::fromString('2024-01-07 23:59:59')
    ],
    period2: [
        'start' => Timestamp::fromString('2024-01-08 00:00:00'),
        'end' => Timestamp::fromString('2024-01-14 23:59:59')
    ]
);

echo "Period 1 Events: {$comparison['period1']['count']}";
echo "Period 2 Events: {$comparison['period2']['count']}";
echo "Change: {$comparison['comparison']['count_change']} ({$comparison['comparison']['count_change_percent']}%)";
```

## CLI Commands

### replay:events - Events replaying

```bash
# Alle Events eines Aggregates
docker exec php php console.php replay:events order-123

# Mit spezifischer Strategy
docker exec php php console.php replay:events order-123 from-version --version=10
docker exec php php console.php replay:events order-123 time-range --days=7
docker exec php php console.php replay:events order-123 today
docker exec php php console.php replay:events order-123 yesterday
```

**Output**:
```
Replaying events for aggregate: order-123
Strategy: Full Replay Strategy

[1] Version 1: OrderPlacedEvent @ 2024-01-15 10:00:00
[2] Version 2: OrderItemAddedEvent @ 2024-01-15 10:05:00
[3] Version 3: OrderCompletedEvent @ 2024-01-15 10:30:00

Total events replayed: 3
```

### replay:time-travel - Time Travel Debugging

```bash
# Zustand zu bestimmter Zeit
docker exec php php console.php replay:time-travel order-123 '2024-01-15 14:30:00'
```

**Output**:
```
Time traveling to: 2024-01-15 14:30:00

State reconstruction would happen here
(Requires aggregate factory implementation)
```

### replay:timeline - Event Timeline

```bash
docker exec php php console.php replay:timeline order-123
```

**Output**:
```
Event Timeline for: order-123
================================================================================

Statistics:
  Total Events: 15
  Time Span: 48 hours
  Avg Events/Day: 7.5
  Unique Event Types: 5

Timeline:
--------------------------------------------------------------------------------
v1     2024-01-15 10:00:00  OrderPlacedEvent
v2     2024-01-15 10:05:00  OrderItemAddedEvent
v3     2024-01-15 10:10:00  OrderItemAddedEvent
v4     2024-01-15 10:30:00  OrderCompletedEvent
```

### replay:stats - Event Statistiken

```bash
docker exec php php console.php replay:stats order-123
```

**Output**:
```
Event Stream Summary
================================================================================

Aggregate ID: order-123
Total Events: 15

First Event:
  Version: 1
  Type: OrderPlacedEvent
  Timestamp: 2024-01-15 10:00:00

Last Event:
  Version: 15
  Type: OrderShippedEvent
  Timestamp: 2024-01-17 10:00:00

Time Span:
  Duration: 48 hours
  Avg Events/Day: 7.5

Event Type Distribution:
  OrderPlacedEvent              1 (  6.7%)
  OrderItemAddedEvent           8 ( 53.3%)
  OrderCompletedEvent           1 (  6.7%)
  OrderPaymentProcessedEvent    1 (  6.7%)
  OrderShippedEvent             1 (  6.7%)
```

### replay:rebuild-projection - Projektion neu aufbauen

```bash
# Einzelne Projektion
docker exec php php console.php replay:rebuild-projection user_statistics

# Mit Strategy
docker exec php php console.php replay:rebuild-projection order_totals --strategy=last-7-days
```

**Output**:
```
Rebuilding projection: user_statistics...
✓ Projection rebuilt successfully
Strategy: full
Status: completed
Last Version: 1523
```

### replay:rebuild-all - Alle Projektionen neu aufbauen

```bash
docker exec php php console.php replay:rebuild-all
```

**Output**:
```
Rebuilding all projections...
✓ All projections rebuilt successfully
Total: 5 projection(s)
  - user_statistics: completed
  - order_totals: completed
  - product_inventory: completed
  - sales_report: completed
  - customer_insights: completed
```

## Verwendungsbeispiele

### Beispiel 1: Debugging mit Time Travel

```php
// Problem: Order zeigt falschen Total-Betrag
$orderId = new OrderId('order-123');

// 1. Wann wurde der Total-Betrag falsch?
$debugger = $container->get(TimeTravelDebugger::class);
$aggregateFactory = fn() => new Order($orderId);

$result = $debugger->findWhenConditionBecameTrue(
    aggregateId: $orderId,
    aggregateFactory: $aggregateFactory,
    condition: fn(Order $order) => $order->getTotal()->cents > 100000 // > 1000€
);

if ($result) {
    echo "Kritischer Betrag erreicht bei Version: {$result['version']}";

    // 2. Welches Event war schuld?
    $visualizer = $container->get(EventHistoryVisualizer::class);
    $timeline = $visualizer->generateTimeline($orderId);

    $criticalEvent = array_filter(
        $timeline['timeline'],
        fn($entry) => $entry['version'] === $result['version']
    );

    echo "Schuld war: " . $criticalEvent[0]['event_type'];
}
```

### Beispiel 2: Projektion reparieren

```php
// Problem: UserStatisticsProjection zeigt falsche Daten

// 1. Projektion komplett neu aufbauen
$rebuilder = $container->get(ProjectionRebuilder::class);
$result = $rebuilder->rebuildProjection('user_statistics');

if ($result['status'] === 'completed') {
    echo "Projektion erfolgreich repariert!";
    echo "Letzte Version: {$result['last_version']}";
}

// 2. Nur letzte 24h neu aufbauen (schneller)
$strategy = TimeRangeReplayStrategy::lastHours(24);
$result = $rebuilder->rebuildProjection('user_statistics', $strategy);
```

### Beispiel 3: Event-Pattern-Analyse

```php
// Analysiere Nutzerverhalten über Zeit
$visualizer = $container->get(EventHistoryVisualizer::class);

$userId = new UserId('user-456');

// Event-Verteilung nach Stunde
$hourlyFrequency = $visualizer->getEventFrequencyByHour($userId);

// Wann ist User am aktivsten?
$mostActiveHour = array_search(max($hourlyFrequency), $hourlyFrequency);
echo "User ist am aktivsten um {$mostActiveHour}:00 Uhr";

// Event-Typen-Verteilung
$distribution = $visualizer->getEventTypeDistribution($userId);
arsort($distribution);

echo "Häufigste Aktionen:";
foreach (array_slice($distribution, 0, 5) as $eventType => $count) {
    echo "- {$eventType}: {$count}x";
}
```

### Beispiel 4: Custom Replay mit Callback

```php
// Replay mit Logger-Callback
$replayer = $container->get(EventReplayer::class);
$logger = $container->get(Logger::class);

$strategy = TimeRangeReplayStrategy::lastDays(7);

$count = $replayer->replayWithCallback(
    aggregateId: new OrderId('order-123'),
    strategy: $strategy,
    callback: function(AggregateEnvelope $envelope) use ($logger) {
        $logger->info('Replaying event', [
            'version' => $envelope->version,
            'event_type' => get_class($envelope->event),
            'timestamp' => $envelope->timestamp->format('Y-m-d H:i:s')
        ]);

        // Custom Business Logic
        if ($envelope->event instanceof OrderCompletedEvent) {
            // Trigger notification or metric
        }
    }
);

echo "Replayed {$count} events with logging";
```

## Integration mit anderen Systemen

### Integration mit Projections

```php
// Projektion mit Replay synchronisieren
final readonly class OrderTotalsProjection implements ProjectionInterface
{
    public function rebuild(): void
    {
        $rebuilder = $this->container->get(ProjectionRebuilder::class);
        $rebuilder->rebuildProjectionForAggregate($this, $this->aggregateId);
    }
}
```

### Integration mit Snapshots

```php
// Snapshot ab bestimmter Version neu aufbauen
$strategy = new FromVersionReplayStrategy($snapshot->version + 1);
$events = $replayer->replayAggregate($aggregateId, $strategy);

foreach ($events as $envelope) {
    $aggregate->apply($envelope->event);
}
```

### Integration mit Sagas

```php
// Saga-Execution debuggen via Replay
$strategy = EventTypeReplayStrategy::forType(SagaStartedEvent::class);
$sagaStartEvents = $replayer->replayAggregate($sagaId, $strategy);

foreach ($sagaStartEvents as $envelope) {
    echo "Saga gestartet: {$envelope->timestamp->format('Y-m-d H:i:s')}";
}
```

## Testing

### Unit Tests für Replay Strategies

```php
describe('TimeRangeReplayStrategy', function () {
    it('filters events within time range', function () {
        $strategy = new TimeRangeReplayStrategy(
            startTime: Timestamp::fromString('2024-01-15 10:00:00'),
            endTime: Timestamp::fromString('2024-01-15 12:00:00')
        );

        $events = [
            $this->createEvent('2024-01-15 09:00:00'), // Before range
            $this->createEvent('2024-01-15 11:00:00'), // In range
            $this->createEvent('2024-01-15 13:00:00'), // After range
        ];

        $filtered = $strategy->selectEvents($events);

        expect($filtered)->toHaveCount(1);
        expect($filtered[0]->timestamp->format('H:i'))->toBe('11:00');
    });

    it('provides factory methods', function () {
        $today = TimeRangeReplayStrategy::today();
        expect($today)->toBeInstanceOf(TimeRangeReplayStrategy::class);

        $yesterday = TimeRangeReplayStrategy::yesterday();
        expect($yesterday)->toBeInstanceOf(TimeRangeReplayStrategy::class);

        $lastWeek = TimeRangeReplayStrategy::lastDays(7);
        expect($lastWeek)->toBeInstanceOf(TimeRangeReplayStrategy::class);
    });
});
```

### Integration Tests für Time Travel

```php
describe('TimeTravelDebugger', function () {
    it('reconstructs state at specific time', function () {
        // Setup: Create events
        $orderId = new OrderId('order-test');
        $this->createOrderEvents($orderId);

        // Time travel to middle of event stream
        $debugger = $this->container->get(TimeTravelDebugger::class);
        $targetTime = Timestamp::fromString('2024-01-15 11:00:00');

        $state = $debugger->getStateAtTime(
            aggregateId: $orderId,
            targetTime: $targetTime,
            aggregateFactory: fn() => new Order($orderId)
        );

        expect($state)->not->toBeNull();
        expect($state->getStatus())->toBe('pending');
    });

    it('finds when condition became true', function () {
        $orderId = new OrderId('order-test');
        $this->createOrderEvents($orderId);

        $debugger = $this->container->get(TimeTravelDebugger::class);

        $result = $debugger->findWhenConditionBecameTrue(
            aggregateId: $orderId,
            aggregateFactory: fn() => new Order($orderId),
            condition: fn(Order $order) => $order->isCompleted()
        );

        expect($result)->not->toBeNull();
        expect($result['version'])->toBeGreaterThan(0);
    });
});
```

### Integration Tests für Projection Rebuilding

```php
describe('ProjectionRebuilder', function () {
    it('rebuilds projection from event history', function () {
        $rebuilder = $this->container->get(ProjectionRebuilder::class);

        // Clear projection
        $this->clearProjection('user_statistics');

        // Rebuild
        $result = $rebuilder->rebuildProjection('user_statistics');

        expect($result['status'])->toBe('completed');
        expect($result['last_version'])->toBeGreaterThan(0);

        // Verify projection data
        $projection = $this->getProjection('user_statistics');
        expect($projection->getData())->not->toBeEmpty();
    });

    it('rebuilds with time range strategy', function () {
        $rebuilder = $this->container->get(ProjectionRebuilder::class);
        $strategy = TimeRangeReplayStrategy::lastDays(7);

        $result = $rebuilder->rebuildProjection('order_totals', $strategy);

        expect($result['status'])->toBe('completed');
        expect($result['strategy'])->toContain('TimeRange');
    });
});
```

## Best Practices

### 1. Replay Strategy Auswahl

**FullReplayStrategy**:
- ✅ Komplette Projektion neu aufbauen
- ✅ Debugging von Anfang bis Ende
- ❌ Performance bei großen Event-Streams

**FromVersionReplayStrategy**:
- ✅ Schneller für partielle Updates
- ✅ Gut nach Snapshots
- ❌ Benötigt bekannte Version

**TimeRangeReplayStrategy**:
- ✅ Zeitbasiertes Debugging
- ✅ Analyse von Zeiträumen
- ❌ Zeitstempel müssen korrekt sein

**EventTypeReplayStrategy**:
- ✅ Fokussierte Analyse
- ✅ Performance bei spezifischen Events
- ❌ Verliert Kontext anderer Events

### 2. Time Travel Best Practices

```php
// ✅ Aggregate Factory verwenden
$aggregateFactory = fn() => new Order($orderId);
$state = $debugger->getStateAtTime($orderId, $targetTime, $aggregateFactory);

// ❌ Aggregate direkt instanziieren
// $state = $debugger->getStateAtTime($orderId, $targetTime, new Order($orderId));
// Problem: Aggregate wird nur einmal erstellt, nicht bei jedem Replay
```

### 3. Performance-Optimierung

```php
// ✅ Batch-Replay für mehrere Aggregates
$aggregateIds = [...]; // Viele IDs
$strategy = TimeRangeReplayStrategy::lastDays(7);

foreach ($aggregateIds as $id) {
    $replayer->replayWithCallback($id, $strategy, $callback);

    // Memory cleanup nach jedem Aggregate
    gc_collect_cycles();
}

// ❌ Alle Events auf einmal laden
// $allEvents = $replayer->replayAggregate($id, new FullReplayStrategy());
// Problem: Memory-Issues bei großen Streams
```

### 4. Error Handling

```php
// ✅ Graceful Error Handling
try {
    $state = $debugger->getStateAtTime($orderId, $targetTime, $aggregateFactory);
} catch (\Exception $e) {
    $this->logger->error('Time travel failed', [
        'aggregate_id' => $orderId->toString(),
        'target_time' => $targetTime->format('Y-m-d H:i:s'),
        'error' => $e->getMessage()
    ]);

    // Fallback zu aktuellem Zustand
    $state = $this->loadCurrentState($orderId);
}
```

### 5. Monitoring & Logging

```php
// ✅ Replay-Operations loggen
$replayer->replayWithCallback(
    aggregateId: $orderId,
    strategy: $strategy,
    callback: function(AggregateEnvelope $envelope) {
        $this->logger->debug('Event replayed', [
            'version' => $envelope->version,
            'event' => class_basename(get_class($envelope->event)),
            'timestamp' => $envelope->timestamp->format('Y-m-d H:i:s')
        ]);
    }
);
```

## Troubleshooting

### Problem: Time Travel liefert null

**Ursachen**:
- Keine Events im Event Store
- Target Time vor erstem Event
- Aggregate Factory fehlerhaft

**Lösung**:
```php
$state = $debugger->getStateAtTime($orderId, $targetTime, $aggregateFactory);

if (!$state) {
    // Check Event Store
    $events = $eventStore->loadStream($orderId);

    if (empty($events)) {
        echo "Keine Events für Aggregate";
    } else {
        $first = reset($events);
        echo "Erstes Event: {$first->timestamp->format('Y-m-d H:i:s')}";

        if ($targetTime->isBefore($first->timestamp)) {
            echo "Target Time ist vor erstem Event!";
        }
    }
}
```

### Problem: Projektion-Rebuild schlägt fehl

**Ursachen**:
- Projektion nicht registriert
- Event Handler fehlt
- Datenbank-Verbindung

**Lösung**:
```php
try {
    $result = $rebuilder->rebuildProjection('user_statistics');
} catch (ProjectionNotFoundException $e) {
    echo "Projektion nicht gefunden - registriert?";
} catch (EventHandlerException $e) {
    echo "Event Handler Fehler: {$e->getMessage()}";
} catch (\Exception $e) {
    echo "Unerwarteter Fehler: {$e->getMessage()}";
}
```

### Problem: Replay zu langsam

**Ursachen**:
- Zu viele Events
- Keine Strategy-Filterung
- Fehlende Indizes

**Lösungen**:

1. **Strategy verwenden**:
```php
// Statt Full Replay
$strategy = TimeRangeReplayStrategy::lastDays(30);
$events = $replayer->replayAggregate($orderId, $strategy);
```

2. **Batch Processing**:
```php
$batchSize = 1000;
$offset = 0;

while ($events = $this->loadEventsBatch($offset, $batchSize)) {
    foreach ($events as $event) {
        // Process event
    }
    $offset += $batchSize;
    gc_collect_cycles();
}
```

3. **Snapshot verwenden**:
```php
// Latest Snapshot laden
$snapshot = $snapshotStore->getLatest($orderId);

// Nur Events seit Snapshot replaying
$strategy = new FromVersionReplayStrategy($snapshot->version + 1);
$events = $replayer->replayAggregate($orderId, $strategy);
```

## Framework-Integration

Das Replay & Time Travel System integriert nahtlos mit anderen Framework-Komponenten:

### Event Store Integration
```php
// EventReplayer nutzt EventStore direkt
final readonly class EventReplayer
{
    public function __construct(
        private EventStore $eventStore
    ) {}
}
```

### Projections Integration
```php
// ProjectionRebuilder nutzt ProjectionManager
final readonly class ProjectionRebuilder
{
    public function __construct(
        private EventStore $eventStore,
        private EventReplayer $replayer,
        private ProjectionManager $projectionManager
    ) {}
}
```

### DI Container Integration
```php
// Alle Komponenten via #[Initializer] auto-registriert
final readonly class ReplayInitializer
{
    #[Initializer]
    public function initializeEventReplayer(EventStore $eventStore): EventReplayer
    {
        return new EventReplayer($eventStore);
    }
}
```

### CLI Commands Integration
```php
// ReplayCommands nutzen Framework's ConsoleCommand System
#[ConsoleCommand('replay:events', 'Replay events for aggregate')]
public function events(ConsoleInput $input): int
{
    // Implementation
}
```

## Zusammenfassung

Das Event Replay & Time Travel System bietet:

✅ **5 Flexible Replay Strategies** für verschiedene Use Cases
✅ **Time Travel Debugging** für historische Zustands-Rekonstruktion
✅ **Projection Rebuilding** mit Strategy-Support
✅ **Event History Visualization** für Stream-Analyse
✅ **Umfassende CLI Tools** für Debugging und Wartung
✅ **Framework-Integration** mit Event Store, Projections, DI Container
✅ **Production-Ready** mit Error Handling, Logging, Performance-Optimierung

Das System ermöglicht:
- **Debugging**: Verstehe was in der Vergangenheit passiert ist
- **Recovery**: Repariere korrupte Projektionen
- **Analysis**: Analysiere Event-Patterns und User-Behavior
- **Testing**: Teste Aggregate-Logic mit historischen Events
- **Maintenance**: Halte Projektionen synchron mit Event-Historie

Alle Komponenten folgen Framework-Patterns:
- **Readonly Classes** für Unveränderlichkeit
- **Value Objects** (Timestamp, Duration, Strategy)
- **Dependency Injection** via Constructor
- **Attribute-based Discovery** (#[Initializer], #[ConsoleCommand])
- **Strategy Pattern** für Extensibility
