import { PathnameInterpreter } from './PathnameInterpreter';
import { RouteAccessPolicy } from './RouteAccessPolicy';
import { SessionGateway } from '../gateways/SessionGateway';
import { AuthRedirectBuilder } from './AuthRedirectBuilder';
import { ConsoleLogger } from '../infrastructure/logging/ConsoleLogger';

const logger = new ConsoleLogger();

export type RouteGuardResult =
  | { type: 'allow' }
  | { type: 'redirect'; to: string };

export class RouteGuard {
  constructor(
    private readonly interpreter: PathnameInterpreter,
    private readonly policy: RouteAccessPolicy,
    private readonly gateway: SessionGateway,
    private readonly builder: AuthRedirectBuilder
  ) {}

  async enforce({ pathname }: { pathname: string }): Promise<RouteGuardResult> {
    logger.info('[RouteGuard] enforce called', { pathname });
    
    // Step 1: Interpret the pathname
    const { logicalPathname } = this.interpreter.interpret(pathname);
    logger.info('[RouteGuard] logicalPathname', { logicalPathname });

    // Step 2: Check if public non-auth page
    if (this.policy.isPublic(logicalPathname) && !this.policy.isAuthPage(logicalPathname)) {
      logger.info('[RouteGuard] Public non-auth page, allowing access');
      return { type: 'allow' };
    }

    // Step 3: Handle auth pages
    if (this.policy.isAuthPage(logicalPathname)) {
      logger.info('[RouteGuard] Auth page detected');
      const session = await this.gateway.getSession();
      if (session) {
        // User is logged in, redirect away from auth page
        const redirectPath = this.builder.awayFromAuthPage({ session, currentPathname: pathname });
        logger.info('[RouteGuard] Redirecting away from auth page', { redirectPath });
        return { type: 'redirect', to: redirectPath };
      }
      // No session, allow access to auth page
      logger.info('[RouteGuard] No session, allowing access to auth page');
      return { type: 'allow' };
    }

    // Step 4: Handle protected pages
    const session = await this.gateway.getSession();
    logger.info('[RouteGuard] Protected page, session', { hasSession: !!session, role: session?.user?.role, sessionData: JSON.stringify(session, null, 2) });
    
    // No session, redirect to login
    if (!session) {
      const loginPath = this.builder.toLogin({ currentPathname: pathname });
      logger.info('[RouteGuard] No session, redirecting to login', { loginPath });
      return { type: 'redirect', to: loginPath };
    }

    // Check required roles
    const reqRoles = this.policy.requiredRoles(logicalPathname);
    logger.info('[RouteGuard] Checking required roles', { reqRoles, userRole: session.user?.role });
    if (reqRoles && session.user?.role && !reqRoles.includes(session.user.role)) {
      const loginPath = this.builder.toLogin({ currentPathname: pathname });
      logger.info('[RouteGuard] Role mismatch, redirecting to login', { loginPath, reqRoles, userRole: session.user.role });
      return { type: 'redirect', to: loginPath };
    }

    // All checks passed, allow access
    logger.info('[RouteGuard] All checks passed, allowing access');
    return { type: 'allow' };
  }
}
