<?php

namespace App\Modules\Integrations\Platform\Middleware;

use App\Modules\Admin\Tenancy\Services\TenantContext;
use App\Modules\Integrations\Platform\Repositories\ApiTokenRepository;
use App\Modules\Integrations\Platform\Services\ApiTokenService;
use App\Modules\Integrations\Platform\Support\ApiErrorResponse;
use App\Modules\Integrations\Platform\Support\ApiResponseFactory;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

final class ApiTokenAuthenticate
{
    public function __construct(
        private readonly ApiTokenRepository $tokens,
        private readonly TenantContext $tenantContext,
        private readonly ApiResponseFactory $responses,
    ) {}

    public function handle(Request $request, Closure $next)
    {
        $plain = $request->bearerToken();
        if (! is_string($plain) || $plain === '') {
            return $this->responses->error(
                new ApiErrorResponse('auth.missing_token', 'Missing API token.'),
                401,
            );
        }

        $token = $this->tokens->findByHash(ApiTokenService::hashToken($plain));
        if ($token === null || $token->isRevoked() || $token->isExpired()) {
            return $this->responses->error(
                new ApiErrorResponse('auth.invalid_token', 'Invalid or expired API token.'),
                401,
            );
        }

        $request->attributes->set('api_token', $token);
        $request->attributes->set('tenant_id', (int) $token->tenant_id);
        $prevTenant = $this->tenantContext->tenantId();
        $this->tenantContext->setTenantId((int) $token->tenant_id);

        $this->tokens->touchLastUsed($token, Carbon::now());

        try {
            return $next($request);
        } finally {
            $this->tenantContext->setTenantId($prevTenant);
        }
    }
}

