<?php

declare(strict_types=1);

namespace App\Middleware;

use App\Core\Auth;
use App\Core\Database;
use App\Core\MiddlewareInterface;
use App\Core\Request;
use App\Core\Response;
use App\Core\Tenant;
use App\Helpers\AjaxResponse;

/**
 * AuthMiddleware
 *
 * Attach to any route via ->get(..., middleware: ['auth']). Redirects
 * browser requests to the login page; returns a 401 JSON envelope for
 * AJAX/API requests so vanilla-JS fetch() callers can react without
 * parsing HTML.
 *
 * Also doubles as the tenant gate for the whole CRM app: rather than
 * adding a 'tenant' middleware entry to every one of the ~300 routes
 * in routes/web.php, this checks the Tenant context that
 * Application::resolveTenantContext() already set for every request.
 * A route wrapped in 'auth' (which is effectively every CRM route)
 * automatically requires a valid, unexpired tenant too.
 */
final class AuthMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, callable $next): Response
    {
        if (!Tenant::check()) {
            return Response::redirect(rtrim((string) config('app.marketing_url', config('app.url')), '/'));
        }

        if (Auth::guest()) {
            if ($request->isAjax() || $request->isJson()) {
                return AjaxResponse::unauthorized();
            }

            return Response::redirect(base_url('login'));
        }

        // A session authenticated on another tenant's subdomain is not
        // valid here — log it out rather than trust it.
        if (!$this->userBelongsToTenant((int) Auth::id(), (int) Tenant::id())) {
            Auth::logout();

            return Response::redirect(base_url('login'));
        }

        if (Tenant::isExpired() && !str_starts_with($request->path(), '/billing')) {
            return Response::redirect(base_url('billing/expired'));
        }

        return $next($request);
    }

    private function userBelongsToTenant(int $userId, int $businessLineId): bool
    {
        $stmt = Database::connection()->prepare(
            'SELECT 1 FROM user_business_lines WHERE user_id = :user_id AND business_line_id = :bl LIMIT 1'
        );
        $stmt->execute(['user_id' => $userId, 'bl' => $businessLineId]);

        return $stmt->fetchColumn() !== false;
    }
}
