/**
 * Enforce Subscription Access Helper
 *
 * Wrapper for API routes that require subscription access checks.
 * Use this in dashboard API routes to enforce payment-based access control.
 *
 * @module middleware/enforce-subscription-access
 *
 * @example
 * // In /app/api/dashboard/workflows/route.ts
 * import { withSubscriptionAccess } from '@/lib/middleware/enforce-subscription-access';
 *
 * export const GET = withSubscriptionAccess(async (req, session) => {
 *   // This code only runs if user has FULL access
 *   const workflows = await prisma.workflows.findMany({ where: { userId: session.userId } });
 *   return NextResponse.json({ workflows });
 * });
 */

import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@/lib/auth';
import { checkUserAccess, type AccessLevel } from '@/lib/utils/subscription-access';
import { logger } from '@/lib/logger';

// Access level constants
const ACCESS_LEVELS = {
  FULL: 'FULL' as AccessLevel,
  LIMITED: 'LIMITED' as AccessLevel,
  READ_ONLY: 'READ_ONLY' as AccessLevel,
  BLOCKED: 'BLOCKED' as AccessLevel,
};

// Access level hierarchy for comparison
const ACCESS_HIERARCHY: Record<AccessLevel, number> = {
  FULL: 3,
  LIMITED: 2,
  READ_ONLY: 1,
  BLOCKED: 0,
};

export interface SessionWithAccess {
  userId: string;
  email: string;
  accessLevel: AccessLevel;
}

type RouteHandler = (
  req: NextRequest,
  session: SessionWithAccess
) => Promise<NextResponse> | NextResponse;

/**
 * Wrap API route handler with subscription access check
 *
 * @param handler - Route handler function
 * @param requiredLevel - Minimum access level required (default: FULL)
 * @returns Wrapped handler that enforces subscription access
 */
export function withSubscriptionAccess(
  handler: RouteHandler,
  requiredLevel: AccessLevel = ACCESS_LEVELS.FULL
) {
  return async (req: NextRequest): Promise<NextResponse> => {
    try {
      // Check authentication first
      const session = await auth();

      if (!session?.user?.id) {
        logger.warn('Unauthenticated access attempt to protected route');
        return NextResponse.json(
          { error: 'Authentication required' },
          { status: 401 }
        );
      }

      const userId = session.user.id;

      // Check subscription access
      const accessResult = await checkUserAccess(userId);

      logger.info('Subscription access check in API route', {
        userId,
        accessLevel: accessResult.accessLevel,
        subscriptionStatus: accessResult.subscriptionStatus,
        requiredLevel,
        path: req.nextUrl.pathname,
      });

      // Check if user is blocked
      if (accessResult.accessLevel === 'BLOCKED') {
        return NextResponse.json(
          {
            error: 'Subscription access denied',
            reason: accessResult.reason,
            subscriptionStatus: accessResult.subscriptionStatus,
            paymentRequired: true,
            action: 'update_payment_method',
          },
          { status: 403 }
        );
      }

      const hasRequiredLevel =
        ACCESS_HIERARCHY[accessResult.accessLevel] >= ACCESS_HIERARCHY[requiredLevel];

      if (!hasRequiredLevel) {
        return NextResponse.json(
          {
            error: 'Insufficient access level',
            currentLevel: accessResult.accessLevel,
            requiredLevel,
            reason: accessResult.reason,
            paymentRequired: accessResult.accessLevel === 'READ_ONLY',
          },
          { status: 403 }
        );
      }

      // Pass session with access level to handler
      const sessionWithAccess: SessionWithAccess = {
        userId,
        email: session.user.email || '',
        accessLevel: accessResult.accessLevel,
      };

      return await handler(req, sessionWithAccess);
    } catch (error) {
      logger.error('Subscription access middleware error', {
        error: error instanceof Error ? error.message : String(error),
        path: req.nextUrl.pathname,
      });

      // Fail open with limited access on errors
      return NextResponse.json(
        {
          error: 'Service temporarily unavailable',
          message: 'Unable to verify subscription status. Please try again.',
        },
        { status: 503 }
      );
    }
  };
}

/**
 * Wrap read-only API route handler (requires READ_ONLY or higher)
 */
export function withReadAccess(handler: RouteHandler) {
  return withSubscriptionAccess(handler, ACCESS_LEVELS.READ_ONLY);
}

/**
 * Wrap limited API route handler (requires LIMITED or higher)
 */
export function withLimitedAccess(handler: RouteHandler) {
  return withSubscriptionAccess(handler, ACCESS_LEVELS.LIMITED);
}
