<?php
/**
 * JWT Authentication Middleware
 */

declare(strict_types=1);

namespace App\Http\Middleware;

use App\Support\Database;
use App\Support\Response;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;

class AuthMiddleware
{
    private string $jwtSecret;
    
    public function __construct(string $jwtSecret)
    {
        $this->jwtSecret = $jwtSecret;
    }
    
    /**
     * Validate JWT token and attach user to request
     */
    public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $authHeader = $request->getHeaderLine('Authorization');
        
        if (empty($authHeader) || !str_starts_with($authHeader, 'Bearer ')) {
            return Response::unauthorized($response ?? $handler->handle($request), 'No token provided');
        }
        
        $token = substr($authHeader, 7);
        
        try {
            $decoded = JWT::decode($token, new Key($this->jwtSecret, 'HS256'));
            
            if ($decoded->type !== 'access') {
                return Response::unauthorized($handler->handle($request), 'Invalid token type');
            }
            
            // Attach auth info to request
            $request = $request->withAttribute('auth', [
                'id' => $decoded->sub,
                'type' => $decoded->user_type,
                'token' => $decoded,
            ]);
            
            return $handler->handle($request);
        } catch (\Firebase\JWT\ExpiredException $e) {
            return Response::unauthorized($handler->handle($request), 'Token expired');
        } catch (\Exception $e) {
            return Response::unauthorized($handler->handle($request), 'Invalid token');
        }
    }
    
    /**
     * Validate that the user is a platform admin
     */
    public static function platformAdmin(ServerRequestInterface $request): ?ResponseInterface
    {
        $auth = $request->getAttribute('auth');
        
        if (!$auth || $auth['type'] !== 'platform_admin') {
            $response = new \Slim\Psr7\Response();
            return Response::forbidden($response, 'Platform admin access required');
        }
        
        return null; // OK
    }
    
    /**
     * Validate that the user is a tenant user (any type)
     */
    public static function tenantUser(ServerRequestInterface $request): ?ResponseInterface
    {
        $auth = $request->getAttribute('auth');
        
        if (!$auth || $auth['type'] !== 'user') {
            $response = new \Slim\Psr7\Response();
            return Response::forbidden($response, 'Tenant user access required');
        }
        
        return null; // OK
    }
    
    /**
     * Validate that the user has a specific user type
     */
    public static function requireUserType(ServerRequestInterface $request, array $types): ?ResponseInterface
    {
        $auth = $request->getAttribute('auth');
        
        if (!$auth || $auth['type'] !== 'user') {
            $response = new \Slim\Psr7\Response();
            return Response::forbidden($response, 'User access required');
        }
        
        $user = Database::fetch('SELECT user_type FROM users WHERE id = $1', [$auth['id']]);
        
        if (!$user || !in_array($user['user_type'], $types)) {
            $response = new \Slim\Psr7\Response();
            return Response::forbidden($response, 'Insufficient permissions');
        }
        
        return null; // OK
    }
}