<?php

namespace App\Services\Analytics;

use App\Models\EventJoinToken;
use App\Models\EventJoinTokenEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

class JoinTokenAnalyticsRecorder
{
    public function record(
        ?EventJoinToken $joinToken,
        string $eventType,
        Request $request,
        array $context = [],
        ?string $providedToken = null,
        ?int $httpStatus = null
    ): void {
        try {
            EventJoinTokenEvent::create($this->buildPayload(
                $joinToken,
                $eventType,
                $request,
                $context,
                $providedToken,
                $httpStatus
            ));
        } catch (\Throwable $exception) {
            // Never block the main request if analytics fails
            report($exception);
        }
    }

    private function buildPayload(
        ?EventJoinToken $joinToken,
        string $eventType,
        Request $request,
        array $context,
        ?string $providedToken,
        ?int $httpStatus
    ): array {
        $route = $request->route();
        $routeName = $route ? $route->getName() : null;
        $deviceId = (string) $request->header('X-Device-Id', $request->input('device_id', ''));
        $deviceId = $deviceId !== '' ? substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $deviceId), 0, 64) : null;

        $tokenHash = null;
        $tokenPreview = null;

        if ($joinToken) {
            $tokenHash = $joinToken->token_hash ?? null;
            $tokenPreview = $joinToken->token_preview ?? null;
        } elseif ($providedToken) {
            $tokenHash = hash('sha256', $providedToken);
            $tokenPreview = $this->buildPreview($providedToken);
        }

        $eventId = $joinToken?->event_id;
        $tenantId = null;

        if ($joinToken && $joinToken->relationLoaded('event')) {
            $tenantId = $joinToken->event?->tenant_id;
        } elseif ($joinToken) {
            $tenantId = $joinToken->event()->value('tenant_id');
        }

        return [
            'event_join_token_id' => $joinToken?->getKey(),
            'event_id' => $eventId,
            'tenant_id' => $tenantId,
            'token_hash' => $tokenHash,
            'token_preview' => $tokenPreview,
            'event_type' => $eventType,
            'route' => $routeName,
            'http_method' => $request->getMethod(),
            'http_status' => $httpStatus,
            'device_id' => $deviceId,
            'ip_address' => $request->ip(),
            'user_agent' => $this->shortenUserAgent($request->userAgent()),
            'context' => $context ?: null,
            'occurred_at' => now(),
        ];
    }

    private function shortenUserAgent(?string $userAgent): ?string
    {
        if ($userAgent === null) {
            return null;
        }

        if (Str::length($userAgent) > 1024) {
            return Str::substr($userAgent, 0, 1024);
        }

        return $userAgent;
    }

    private function buildPreview(string $token): string
    {
        $token = trim($token);
        $length = Str::length($token);

        if ($length <= 10) {
            return $token;
        }

        return Str::substr($token, 0, 6).'…'.Str::substr($token, -4);
    }
}

