<?php

declare(strict_types=1);

namespace App\Framework\StateManagement\Database;

use App\Framework\Attributes\Entity;
use App\Framework\Attributes\Id;
use App\Framework\Attributes\Column;
use App\Framework\Core\ValueObjects\Timestamp;

/**
 * Component State Database Entity
 *
 * Represents current state of a LiveComponent stored in database.
 * EntityManager-compatible entity with attribute-based mapping.
 */
#[Entity(table: 'component_state')]
final readonly class ComponentStateEntity
{
    public function __construct(
        #[Id]
        #[Column(name: 'component_id')]
        public string $componentId,

        #[Column(name: 'state_data', type: 'text')]
        public string $stateData,        // Encrypted state

        #[Column(name: 'state_class')]
        public string $stateClass,

        #[Column(name: 'component_name')]
        public string $componentName,

        #[Column(name: 'user_id')]
        public ?string $userId,

        #[Column(name: 'session_id')]
        public ?string $sessionId,

        #[Column(name: 'version', type: 'integer')]
        public int $version,

        #[Column(name: 'checksum')]
        public string $checksum,         // SHA256 of state_data

        #[Column(name: 'created_at', type: 'datetime')]
        public Timestamp $createdAt,

        #[Column(name: 'updated_at', type: 'datetime')]
        public Timestamp $updatedAt,

        #[Column(name: 'expires_at', type: 'datetime')]
        public ?Timestamp $expiresAt,
    ) {}

    /**
     * Check if state is expired
     */
    public function isExpired(): bool
    {
        if ($this->expiresAt === null) {
            return false;
        }

        return Timestamp::now()->isAfter($this->expiresAt);
    }

    /**
     * Create from database row
     */
    public static function fromRow(array $row): self
    {
        return new self(
            componentId: $row['component_id'],
            stateData: $row['state_data'],
            stateClass: $row['state_class'],
            componentName: $row['component_name'],
            userId: $row['user_id'] ?? null,
            sessionId: $row['session_id'] ?? null,
            version: (int) $row['version'],
            checksum: $row['checksum'],
            createdAt: Timestamp::fromString($row['created_at']),
            updatedAt: Timestamp::fromString($row['updated_at']),
            expiresAt: isset($row['expires_at']) ? Timestamp::fromString($row['expires_at']) : null,
        );
    }

    /**
     * Convert to database row
     */
    public function toRow(): array
    {
        return [
            'component_id' => $this->componentId,
            'state_data' => $this->stateData,
            'state_class' => $this->stateClass,
            'component_name' => $this->componentName,
            'user_id' => $this->userId,
            'session_id' => $this->sessionId,
            'version' => $this->version,
            'checksum' => $this->checksum,
            'created_at' => $this->createdAt->format('Y-m-d H:i:s'),
            'updated_at' => $this->updatedAt->format('Y-m-d H:i:s'),
            'expires_at' => $this->expiresAt?->format('Y-m-d H:i:s'),
        ];
    }

    /**
     * Create new version with updated state
     */
    public function withUpdatedState(
        string $stateData,
        string $checksum,
        ?Timestamp $expiresAt = null
    ): self {
        return new self(
            componentId: $this->componentId,
            stateData: $stateData,
            stateClass: $this->stateClass,
            componentName: $this->componentName,
            userId: $this->userId,
            sessionId: $this->sessionId,
            version: $this->version + 1,
            checksum: $checksum,
            createdAt: $this->createdAt,
            updatedAt: Timestamp::now(),
            expiresAt: $expiresAt,
        );
    }
}
