<?php

namespace App\Modules\Admin\Tenancy\Middleware;

use App\Models\User;
use App\Modules\Admin\Tenancy\Models\Module;
use App\Modules\Admin\Tenancy\Models\Subscription;
use App\Modules\Admin\Tenancy\Services\ModuleAccessService;
use App\Modules\Admin\Tenancy\Services\SubscriptionService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Lang;
use Symfony\Component\HttpFoundation\Response;

class CheckModuleAccess
{
    public function __construct(
        private readonly ModuleAccessService $accessService,
        private readonly SubscriptionService $subscriptionService,
    ) {}

    public function handle(Request $request, Closure $next, string $moduleSlug): Response
    {
        $user = $request->user();

        if ($user === null) {
            abort(401);
        }

        if ($user->isAdmin()) {
            return $next($request);
        }

        $tenant = $user->tenant;
        if ($tenant === null || ! $tenant->is_active) {
            return $this->tenantDeniedResponse();
        }

        if (! $this->accessService->tenantHasModule($tenant, $moduleSlug)) {
            return $this->moduleLockedResponse($user, $moduleSlug);
        }

        return $next($request);
    }

    private function tenantDeniedResponse(): Response
    {
        $upgradeUrl = route('dashboard.index') . '#dashboard-modules';

        return response()->view('pages.tenant.access-denied', [
            'moduleSlug' => '',
            'reason' => 'tenant',
            'upgradeUrl' => $upgradeUrl,
        ], 403);
    }

    private function moduleLockedResponse(User $user, string $moduleSlug): Response
    {
        $user->loadMissing(['tenant.plan', 'tenant.activeSubscription.plan']);
        $module = Module::query()->where('slug', $moduleSlug)->first();
        $tenant = $user->tenant;
        $subscription = $tenant?->activeSubscription;
        if ($tenant && $subscription === null) {
            $subscription = $this->subscriptionService->activeFor($tenant);
        }
        $planName = $subscription?->plan?->name ?? $tenant?->plan?->name;
        $subscriptionStatusKey = 'dashboard.subscription_status.' . ($subscription?->status ?? 'none');
        $nameKey = 'modules.catalog.' . $moduleSlug . '.name';
        $moduleLabel = Lang::has($nameKey) ? (string) __($nameKey) : (string) ($module?->name ?? $moduleSlug);
        $trialDaysLeft = $this->trialDaysLeft($subscription);
        $upgradeUrl = route('dashboard.index') . '#dashboard-modules';

        return response()->view('errors.module-locked', [
            'moduleLabel' => $moduleLabel,
            'planName' => $planName,
            'subscriptionStatusKey' => $subscriptionStatusKey,
            'upgradeUrl' => $upgradeUrl,
            'trialDaysLeft' => $trialDaysLeft,
        ], 403);
    }

    private function trialDaysLeft(?Subscription $subscription): ?int
    {
        if ($subscription?->status !== Subscription::STATUS_TRIAL || $subscription->trial_ends_at === null) {
            return null;
        }
        if (! $subscription->trial_ends_at->isFuture()) {
            return 0;
        }
        $days = (int) now()->startOfDay()->diffInDays(
            $subscription->trial_ends_at->copy()->startOfDay(),
            false
        );

        return max(0, $days);
    }
}
