<?php

declare(strict_types=1);

namespace App\Framework\ErrorReporting\Processors;

use App\Framework\ErrorReporting\ErrorReport;
use App\Framework\Http\Session\Session;

/**
 * Processor that enriches error reports with user context
 */
final readonly class UserContextProcessor
{
    public function __construct(
        private ?Session $session = null
    ) {
    }

    public function __invoke(ErrorReport $report): ErrorReport
    {
        // If already has user context, don't override
        if ($report->userId) {
            return $report;
        }

        // Skip if no session available
        if (! $this->session) {
            return $report;
        }

        // Try to extract user information from session
        $userId = $this->getUserIdFromSession();
        $sessionId = $this->getSessionId();

        if (! $userId && ! $sessionId) {
            return $report;
        }

        $enrichedReport = $report;

        if ($userId || $sessionId) {
            $enrichedReport = $enrichedReport->withUser($userId, $sessionId);
        }

        // Add user-specific tags
        $tags = [];
        if ($userId) {
            $tags[] = 'authenticated';
        } else {
            $tags[] = 'anonymous';
        }

        // Add session-specific information
        if ($sessionId) {
            $tags[] = 'has_session';
        }

        if (! empty($tags)) {
            $enrichedReport = $enrichedReport->withTags($tags);
        }

        // Add breadcrumbs with user actions
        $breadcrumbs = $this->getUserBreadcrumbs();
        if (! empty($breadcrumbs)) {
            $enrichedReport = $enrichedReport->withBreadcrumbs($breadcrumbs);
        }

        return $enrichedReport;
    }

    private function getUserIdFromSession(): ?string
    {
        // Try various common session keys for user ID
        $userIdKeys = ['user_id', 'id', 'user', 'auth_user_id', 'logged_in_user'];

        foreach ($userIdKeys as $key) {
            if ($this->session->has($key)) {
                $userId = $this->session->get($key);

                // Handle user objects
                if (is_object($userId) && isset($userId->id)) {
                    return (string) $userId->id;
                }

                // Handle arrays
                if (is_array($userId) && isset($userId['id'])) {
                    return (string) $userId['id'];
                }

                // Handle simple values
                if (is_scalar($userId)) {
                    return (string) $userId;
                }
            }
        }

        return null;
    }

    private function getSessionId(): ?string
    {
        // Get session ID from framework's session
        return $this->session->getId();
    }

    private function getUserBreadcrumbs(): array
    {
        $breadcrumbs = [];

        // Get from session if available
        if ($this->session->has('user_breadcrumbs')) {
            $sessionBreadcrumbs = $this->session->get('user_breadcrumbs');

            if (is_array($sessionBreadcrumbs)) {
                foreach ($sessionBreadcrumbs as $breadcrumb) {
                    if (is_array($breadcrumb) && isset($breadcrumb['message'])) {
                        $breadcrumbs[] = [
                            'message' => $breadcrumb['message'],
                            'category' => $breadcrumb['category'] ?? 'user_action',
                            'level' => $breadcrumb['level'] ?? 'info',
                            'timestamp' => $breadcrumb['timestamp'] ?? date('c'),
                            'data' => $breadcrumb['data'] ?? null,
                        ];
                    }
                }
            }
        }

        // Add current request as breadcrumb
        if (isset($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'])) {
            $breadcrumbs[] = [
                'message' => "HTTP Request: {$_SERVER['REQUEST_METHOD']} {$_SERVER['REQUEST_URI']}",
                'category' => 'navigation',
                'level' => 'info',
                'timestamp' => date('c'),
                'data' => [
                    'method' => $_SERVER['REQUEST_METHOD'],
                    'uri' => $_SERVER['REQUEST_URI'],
                    'referer' => $_SERVER['HTTP_REFERER'] ?? null,
                ],
            ];
        }

        // Limit breadcrumbs to prevent excessive data
        return array_slice($breadcrumbs, -10);
    }

    /**
     * Helper method to add user breadcrumb (can be called from application code)
     */
    public function addBreadcrumb(
        string $message,
        string $category = 'user_action',
        string $level = 'info',
        ?array $data = null
    ): void {
        if (! $this->session) {
            return;
        }

        $breadcrumbs = $this->session->get('user_breadcrumbs', []);

        $breadcrumbs[] = [
            'message' => $message,
            'category' => $category,
            'level' => $level,
            'timestamp' => date('c'),
            'data' => $data,
        ];

        // Keep only last 20 breadcrumbs
        $breadcrumbs = array_slice($breadcrumbs, -20);

        $this->session->set('user_breadcrumbs', $breadcrumbs);
    }

    /**
     * Helper method to clear user breadcrumbs
     */
    public function clearBreadcrumbs(): void
    {
        if ($this->session) {
            $this->session->remove('user_breadcrumbs');
        }
    }
}
