"use strict";
/**
 * Auth0 Authentication Generator
 * Generates Auth0 SDK integration for both frontend and backend
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Auth0Generator = void 0;
const path = __importStar(require("path"));
class Auth0Generator {
    id = 'auth0-auth';
    name = 'Auth0 Authentication Generator';
    description = 'Generates Auth0 authentication integration';
    generate(context, config = {}) {
        const { outputDirectory } = context;
        const files = [];
        // Generate backend files
        files.push(...this.generateBackendFiles(outputDirectory, config));
        // Generate frontend files
        files.push(...this.generateFrontendFiles(outputDirectory, config));
        return {
            files,
            dependencies: {
                backend: this.getBackendDependencies(),
                frontend: this.getFrontendDependencies(),
            },
        };
    }
    /**
     * Generate backend Auth0 integration
     */
    generateBackendFiles(outputDir, _config) {
        const files = [];
        // 1. Auth0 middleware
        files.push(this.generateAuth0Middleware(outputDir));
        // 2. TypeScript types
        files.push(this.generateBackendTypes(outputDir));
        return files;
    }
    /**
     * Generate Auth0 Express middleware
     */
    generateAuth0Middleware(outputDir) {
        const code = `import { auth, requiredScopes, claimCheck } from 'express-oauth2-jwt-bearer';
import { Request, Response, NextFunction } from 'express';

/**
 * Auth0 JWT validation middleware
 * Validates JWT tokens from Auth0
 */
export const checkJwt = auth({
  audience: process.env.AUTH0_AUDIENCE,
  issuerBaseURL: \`https://\${process.env.AUTH0_DOMAIN}\`,
  tokenSigningAlg: 'RS256',
});

/**
 * Require specific scopes middleware
 * Checks if the JWT has required scopes
 */
export const requireScopes = (scopes: string[]) => {
  return requiredScopes(scopes.join(' '));
};

/**
 * Role-based authorization middleware
 * Checks if the authenticated user has one of the required roles
 */
export const authorize = (allowedRoles: string[]) => {
  return (req: Request, res: Response, next: NextFunction) => {
    const auth = req.auth;

    if (!auth?.payload) {
      return res.status(401).json({ message: 'Not authenticated' });
    }

    // Get user roles from Auth0 custom claims
    const userRoles = (auth.payload['https://your-app.com/roles'] as string[]) || [];

    if (!allowedRoles.some(role => userRoles.includes(role))) {
      return res.status(403).json({ message: 'Insufficient permissions' });
    }

    next();
  };
};

/**
 * Get current user ID from request
 */
export const getCurrentUserId = (req: Request): string | null => {
  return req.auth?.payload?.sub || null;
};

/**
 * Check custom claims
 * Validates custom claims in the JWT
 */
export const checkClaims = (claims: Record<string, any>) => {
  return claimCheck((payload) => {
    for (const [key, value] of Object.entries(claims)) {
      if (payload[key] !== value) {
        return false;
      }
    }
    return true;
  });
};

/**
 * Error handler for Auth0 errors
 */
export const auth0ErrorHandler = (error: Error, req: Request, res: Response, next: NextFunction) => {
  console.error('Auth0 error:', error);

  if (error.name === 'UnauthorizedError') {
    return res.status(401).json({ message: 'Invalid token' });
  }

  res.status(500).json({ message: 'Authentication error' });
};
`;
        return {
            path: path.join(outputDir, 'backend', 'src', 'middleware', 'auth0-auth.ts'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate TypeScript types for Auth0
     */
    generateBackendTypes(outputDir) {
        const code = `import { Request as ExpressRequest } from 'express';

declare global {
  namespace Express {
    interface Request {
      auth?: {
        header: Record<string, any>;
        payload: {
          sub?: string;
          iss?: string;
          aud?: string | string[];
          exp?: number;
          iat?: number;
          scope?: string;
          permissions?: string[];
          [key: string]: any;
        };
        token: string;
      };
    }
  }
}

export {};
`;
        return {
            path: path.join(outputDir, 'backend', 'types', 'auth0.d.ts'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate frontend Auth0 integration
     */
    generateFrontendFiles(outputDir, config) {
        const files = [];
        // 1. Auth0 Provider wrapper
        files.push(this.generateAuth0Provider(outputDir, config));
        // 2. Login page
        files.push(this.generateLoginPage(outputDir));
        // 3. Signup page
        files.push(this.generateSignupPage(outputDir));
        // 4. Auth hooks
        files.push(this.generateAuthHooks(outputDir));
        // 5. Protected Route component
        files.push(this.generateProtectedRoute(outputDir));
        // 6. Callback page
        files.push(this.generateCallbackPage(outputDir));
        return files;
    }
    /**
     * Generate Auth0 Provider wrapper
     */
    generateAuth0Provider(outputDir, _config) {
        const code = `import React from 'react';
import { Auth0Provider as Auth0ProviderSDK } from '@auth0/auth0-react';
import { useNavigate } from 'react-router-dom';

interface AuthProviderProps {
  children: React.ReactNode;
}

export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  const navigate = useNavigate();

  const domain = import.meta.env.VITE_AUTH0_DOMAIN;
  const clientId = import.meta.env.VITE_AUTH0_CLIENT_ID;
  const audience = import.meta.env.VITE_AUTH0_AUDIENCE;

  if (!domain || !clientId) {
    throw new Error('Missing Auth0 configuration. Please set VITE_AUTH0_DOMAIN and VITE_AUTH0_CLIENT_ID');
  }

  const onRedirectCallback = (appState: any) => {
    navigate(appState?.returnTo || window.location.pathname);
  };

  return (
    <Auth0ProviderSDK
      domain={domain}
      clientId={clientId}
      authorizationParams={{
        redirect_uri: window.location.origin + '/callback',
        audience: audience,
        scope: 'openid profile email',
      }}
      onRedirectCallback={onRedirectCallback}
      cacheLocation="localstorage"
    >
      {children}
    </Auth0ProviderSDK>
  );
};
`;
        return {
            path: path.join(outputDir, 'frontend', 'src', 'components', 'AuthProvider.tsx'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate Login page
     */
    generateLoginPage(outputDir) {
        const code = `import React, { useEffect } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { useNavigate } from 'react-router-dom';

export const Login: React.FC = () => {
  const { loginWithRedirect, isAuthenticated, isLoading } = useAuth0();
  const navigate = useNavigate();

  useEffect(() => {
    if (isAuthenticated) {
      navigate('/');
    }
  }, [isAuthenticated, navigate]);

  const handleLogin = () => {
    loginWithRedirect({
      appState: { returnTo: '/' },
    });
  };

  const handleSignup = () => {
    loginWithRedirect({
      appState: { returnTo: '/' },
      authorizationParams: {
        screen_hint: 'signup',
      },
    });
  };

  if (isLoading) {
    return (
      <div className="flex items-center justify-center min-h-screen bg-gray-50">
        <div className="text-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
          <p className="mt-4 text-gray-600">Loading...</p>
        </div>
      </div>
    );
  }

  return (
    <div className="flex items-center justify-center min-h-screen bg-gray-50">
      <div className="w-full max-w-md p-8 space-y-6 bg-white rounded-lg shadow-md">
        <div className="text-center">
          <h1 className="text-3xl font-bold text-gray-900">Welcome</h1>
          <p className="mt-2 text-gray-600">Sign in to your account</p>
        </div>

        <div className="space-y-4">
          <button
            onClick={handleLogin}
            className="w-full px-4 py-3 text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors"
          >
            Sign In
          </button>

          <button
            onClick={handleSignup}
            className="w-full px-4 py-3 text-blue-600 bg-white border border-blue-600 rounded-lg hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors"
          >
            Sign Up
          </button>
        </div>
      </div>
    </div>
  );
};
`;
        return {
            path: path.join(outputDir, 'frontend', 'src', 'pages', 'Login.tsx'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate Signup page (redirects to Auth0 signup)
     */
    generateSignupPage(outputDir) {
        const code = `import React, { useEffect } from 'react';
import { useAuth0 } from '@auth0/auth0-react';

export const Signup: React.FC = () => {
  const { loginWithRedirect } = useAuth0();

  useEffect(() => {
    loginWithRedirect({
      appState: { returnTo: '/' },
      authorizationParams: {
        screen_hint: 'signup',
      },
    });
  }, [loginWithRedirect]);

  return (
    <div className="flex items-center justify-center min-h-screen bg-gray-50">
      <div className="text-center">
        <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
        <p className="mt-4 text-gray-600">Redirecting to signup...</p>
      </div>
    </div>
  );
};
`;
        return {
            path: path.join(outputDir, 'frontend', 'src', 'pages', 'Signup.tsx'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate callback page for OAuth redirect
     */
    generateCallbackPage(outputDir) {
        const code = `import React, { useEffect } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { useNavigate } from 'react-router-dom';

export const Callback: React.FC = () => {
  const { isAuthenticated, isLoading, error } = useAuth0();
  const navigate = useNavigate();

  useEffect(() => {
    if (!isLoading) {
      if (isAuthenticated) {
        navigate('/');
      } else if (error) {
        console.error('Auth0 error:', error);
        navigate('/login');
      }
    }
  }, [isLoading, isAuthenticated, error, navigate]);

  if (error) {
    return (
      <div className="flex items-center justify-center min-h-screen bg-gray-50">
        <div className="text-center">
          <div className="text-red-600 text-xl mb-4">Authentication Error</div>
          <p className="text-gray-600">{error.message}</p>
          <button
            onClick={() => navigate('/login')}
            className="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
          >
            Back to Login
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className="flex items-center justify-center min-h-screen bg-gray-50">
      <div className="text-center">
        <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
        <p className="mt-4 text-gray-600">Completing sign in...</p>
      </div>
    </div>
  );
};
`;
        return {
            path: path.join(outputDir, 'frontend', 'src', 'pages', 'Callback.tsx'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate auth hooks
     */
    generateAuthHooks(outputDir) {
        const code = `import { useAuth0 } from '@auth0/auth0-react';

/**
 * Hook to get current user
 */
export const useCurrentUser = () => {
  const { user, isLoading, isAuthenticated } = useAuth0();

  return {
    user,
    isLoaded: !isLoading,
    isSignedIn: isAuthenticated,
  };
};

/**
 * Hook to get auth functions
 */
export const useAuthFunctions = () => {
  const { logout, getAccessTokenSilently } = useAuth0();

  const signOut = () => {
    logout({
      logoutParams: {
        returnTo: window.location.origin,
      },
    });
  };

  const getToken = async () => {
    try {
      return await getAccessTokenSilently();
    } catch (error) {
      console.error('Error getting access token:', error);
      return null;
    }
  };

  return {
    signOut,
    getToken,
  };
};

/**
 * Hook to check if user has a specific role
 */
export const useHasRole = (role: string): boolean => {
  const { user } = useAuth0();
  const roles = (user?.['https://your-app.com/roles'] as string[]) || [];
  return roles.includes(role);
};

/**
 * Hook to check if user has specific permissions
 */
export const useHasPermission = (permission: string): boolean => {
  const { user } = useAuth0();
  const permissions = (user?.permissions as string[]) || [];
  return permissions.includes(permission);
};
`;
        return {
            path: path.join(outputDir, 'frontend', 'src', 'hooks', 'useAuth.ts'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate Protected Route component
     */
    generateProtectedRoute(outputDir) {
        const code = `import React from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { Navigate } from 'react-router-dom';

interface ProtectedRouteProps {
  children: React.ReactNode;
  requiredRoles?: string[];
  requiredPermissions?: string[];
}

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  children,
  requiredRoles = [],
  requiredPermissions = [],
}) => {
  const { isAuthenticated, isLoading, user } = useAuth0();

  // Show loading state while auth is initializing
  if (isLoading) {
    return (
      <div className="flex items-center justify-center min-h-screen">
        <div className="text-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
          <p className="mt-4 text-gray-600">Loading...</p>
        </div>
      </div>
    );
  }

  // Redirect to login if not authenticated
  if (!isAuthenticated) {
    return <Navigate to="/login" replace />;
  }

  // Check roles if required
  if (requiredRoles.length > 0) {
    const userRoles = (user?.['https://your-app.com/roles'] as string[]) || [];
    if (!requiredRoles.some(role => userRoles.includes(role))) {
      return <Navigate to="/unauthorized" replace />;
    }
  }

  // Check permissions if required
  if (requiredPermissions.length > 0) {
    const userPermissions = (user?.permissions as string[]) || [];
    if (!requiredPermissions.some(perm => userPermissions.includes(perm))) {
      return <Navigate to="/unauthorized" replace />;
    }
  }

  return <>{children}</>;
};
`;
        return {
            path: path.join(outputDir, 'frontend', 'src', 'components', 'ProtectedRoute.tsx'),
            content: code,
            overwrite: true,
        };
    }
    /**
     * Generate environment variable template
     */
    generateEnvTemplate() {
        return `# Auth0 Configuration
# Backend
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_AUDIENCE=https://your-api-identifier

# Frontend
VITE_AUTH0_DOMAIN=your-tenant.auth0.com
VITE_AUTH0_CLIENT_ID=your_auth0_client_id
VITE_AUTH0_AUDIENCE=https://your-api-identifier
`;
    }
    /**
     * Get required npm dependencies for backend
     */
    getBackendDependencies() {
        return {
            'express-oauth2-jwt-bearer': '^1.6.0',
        };
    }
    /**
     * Get required npm dependencies for frontend
     */
    getFrontendDependencies() {
        return {
            '@auth0/auth0-react': '^2.2.0',
        };
    }
}
exports.Auth0Generator = Auth0Generator;
//# sourceMappingURL=auth0-generator.js.map