<?php

declare(strict_types=1);

namespace App\Framework\Exception;

/**
 * Fachlicher Kontext für Exceptions - nur domain-spezifische Informationen
 */
final readonly class ExceptionContext
{
    public function __construct(
        public ?string $operation = null,
        public ?string $component = null,
        public array $data = [],
        public array $debug = [],
        public array $metadata = []
    ) {}

    public static function empty(): self
    {
        return new self();
    }

    public static function forOperation(string $operation, ?string $component = null): self
    {
        return new self(operation: $operation, component: $component);
    }

    public function withOperation(string $operation, ?string $component = null): self
    {
        return new self(
            operation: $operation,
            component: $component ?? $this->component,
            data: $this->data,
            debug: $this->debug,
            metadata: $this->metadata
        );
    }

    public function withData(array $data): self
    {
        return new self(
            operation: $this->operation,
            component: $this->component,
            data: array_merge($this->data, $data),
            debug: $this->debug,
            metadata: $this->metadata
        );
    }

    public function withDebug(array $debug): self
    {
        return new self(
            operation: $this->operation,
            component: $this->component,
            data: $this->data,
            debug: array_merge($this->debug, $debug),
            metadata: $this->metadata
        );
    }

    public function withMetadata(array $metadata): self
    {
        return new self(
            operation: $this->operation,
            component: $this->component,
            data: $this->data,
            debug: $this->debug,
            metadata: array_merge($this->metadata, $metadata)
        );
    }

    public function toArray(): array
    {
        return [
            'operation' => $this->operation,
            'component' => $this->component,
            'data' => $this->sanitizeData($this->data),
            'debug' => $this->debug,
            'metadata' => $this->metadata
        ];
    }

    private function sanitizeData(array $data): array
    {
        $sensitiveKeys = ['password', 'token', 'api_key', 'secret', 'private_key'];

        array_walk_recursive($data, function (&$value, $key) use ($sensitiveKeys) {
            if (in_array(strtolower($key), $sensitiveKeys)) {
                $value = '[REDACTED]';
            }
        });

        return $data;
    }
}
