<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Profiling;

use App\Framework\Core\ValueObjects\Byte;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\LiveComponents\Profiling\ValueObjects\MemorySnapshot;
use App\Framework\LiveComponents\Profiling\ValueObjects\ProfilePhase;
use App\Framework\LiveComponents\Profiling\ValueObjects\ProfileSessionId;
use App\Framework\Telemetry\OperationHandle;

/**
 * Active profiling session for a LiveComponent
 *
 * Tracks component lifecycle with phases, memory snapshots, and telemetry integration.
 */
final class ProfileSession
{
    /** @var array<ProfilePhase> */
    public array $phases = [];

    /** @var array<MemorySnapshot> */
    public array $memorySnapshots = [];

    public function __construct(
        public readonly ProfileSessionId $sessionId,
        public readonly string $componentId,
        public readonly OperationHandle $operation,
        public readonly Byte $startMemory,
        public readonly Timestamp $startTime
    ) {
    }

    /**
     * Add a lifecycle phase
     */
    public function addPhase(ProfilePhase $phase): void
    {
        $this->phases[] = $phase;
    }

    /**
     * Add memory snapshot
     */
    public function addMemorySnapshot(MemorySnapshot $snapshot): void
    {
        $this->memorySnapshots[] = $snapshot;
    }

    /**
     * Get all phases
     *
     * @return array<ProfilePhase>
     */
    public function getPhases(): array
    {
        return $this->phases;
    }

    /**
     * Get all memory snapshots
     *
     * @return array<MemorySnapshot>
     */
    public function getMemorySnapshots(): array
    {
        return $this->memorySnapshots;
    }

    /**
     * Get phase by name
     */
    public function getPhase(string $name): ?ProfilePhase
    {
        foreach ($this->phases as $phase) {
            if ($phase->name === $name) {
                return $phase;
            }
        }

        return null;
    }

    /**
     * Get total duration of all phases
     */
    public function getTotalPhaseDuration(): Duration
    {
        $totalMs = 0.0;

        foreach ($this->phases as $phase) {
            $totalMs += $phase->getDurationMs();
        }

        return Duration::fromMilliseconds($totalMs);
    }

    /**
     * Get total memory delta across all phases
     */
    public function getTotalPhaseMemory(): Byte
    {
        $totalBytes = 0;

        foreach ($this->phases as $phase) {
            $totalBytes += $phase->getMemoryBytes();
        }

        return Byte::fromBytes($totalBytes);
    }

    /**
     * Get elapsed time since session start
     */
    public function getElapsedTime(): Duration
    {
        return Timestamp::now()->diff($this->startTime);
    }
}
