/**
 * Protected Route component for handling authentication and authorization
 *
 * This component integrates with the unified permission system to provide
 * comprehensive access control for routes. It checks both global user roles
 * and tenant-specific permissions.
 *
 * For permission checking logic, see utils/permissions.ts
 */

import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { useAuthUser, useIsAuthenticated, useAuthLoading } from '../stores';
import { useCurrentTenant, useCurrentTenantAccess, useTenantPermissions } from '../stores/tenant.store';
import { useHasAccess, useIsDemoMode } from '../hooks/useAccessControl';
import { RouteConfig, canAccessRoute, ROUTES } from './routes.config';
import { checkCombinedPermission, type User, type TenantAccess } from '../utils/permissions';

interface ProtectedRouteProps {
  children: React.ReactNode;
  route?: RouteConfig;
  fallback?: React.ReactNode;
  redirectTo?: string;
}

interface LoadingSpinnerProps {
  message?: string;
}

const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({ message = 'Cargando...' }) => (
  <div className="flex items-center justify-center min-h-screen bg-bg-primary">
    <div className="flex flex-col items-center gap-4">
      <div className="spinner spinner-lg"></div>
      <p className="text-text-secondary text-sm">{message}</p>
    </div>
  </div>
);

const UnauthorizedPage: React.FC = () => (
  <div className="flex items-center justify-center min-h-screen bg-bg-primary">
    <div className="text-center max-w-md mx-auto px-6">
      <div className="mb-6">
        <div className="w-16 h-16 mx-auto mb-4 bg-color-error rounded-full flex items-center justify-center">
          <svg 
            className="w-8 h-8 text-text-inverse" 
            fill="none" 
            stroke="currentColor" 
            viewBox="0 0 24 24"
          >
            <path 
              strokeLinecap="round" 
              strokeLinejoin="round" 
              strokeWidth={2} 
              d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.732 19.5c-.77.833.192 2.5 1.732 2.5z" 
            />
          </svg>
        </div>
        <h1 className="text-2xl font-bold text-text-primary mb-2">
          Acceso no autorizado
        </h1>
        <p className="text-text-secondary mb-6">
          No tienes permisos para acceder a esta página. Contacta con tu administrador si crees que esto es un error.
        </p>
      </div>
      
      <div className="flex flex-col gap-3">
        <button
          onClick={() => window.history.back()}
          className="btn btn-primary"
        >
          Volver atrás
        </button>
        <button
          onClick={() => window.location.href = ROUTES.DASHBOARD}
          className="btn btn-outline"
        >
          Ir al Panel de Control
        </button>
      </div>
    </div>
  </div>
);

const ForbiddenPage: React.FC = () => (
  <div className="flex items-center justify-center min-h-screen bg-bg-primary">
    <div className="text-center max-w-md mx-auto px-6">
      <div className="mb-6">
        <div className="w-16 h-16 mx-auto mb-4 bg-color-warning rounded-full flex items-center justify-center">
          <svg 
            className="w-8 h-8 text-text-inverse" 
            fill="none" 
            stroke="currentColor" 
            viewBox="0 0 24 24"
          >
            <path 
              strokeLinecap="round" 
              strokeLinejoin="round" 
              strokeWidth={2} 
              d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L5.636 5.636" 
            />
          </svg>
        </div>
        <h1 className="text-2xl font-bold text-text-primary mb-2">
          Acceso restringido
        </h1>
        <p className="text-text-secondary mb-6">
          Tu cuenta no tiene los permisos necesarios para ver esta sección. Contacta con tu administrador para solicitar acceso.
        </p>
      </div>
      
      <div className="flex flex-col gap-3">
        <button
          onClick={() => window.history.back()}
          className="btn btn-primary"
        >
          Volver atrás
        </button>
        <button
          onClick={() => window.location.href = ROUTES.DASHBOARD}
          className="btn btn-outline"
        >
          Ir al Panel de Control
        </button>
      </div>
    </div>
  </div>
);

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  children,
  route,
  fallback,
  redirectTo,
}) => {
  const user = useAuthUser();
  const isAuthenticated = useIsAuthenticated();
  const isLoading = useAuthLoading();
  const currentTenant = useCurrentTenant();
  const currentTenantAccess = useCurrentTenantAccess();
  const { hasPermission } = useTenantPermissions();
  const location = useLocation();
  const hasAccess = useHasAccess(); // Check both authentication and demo mode
  const isDemoMode = useIsDemoMode();

  // Note: Onboarding routes are now properly protected and require authentication
  // Mock mode only applies to the onboarding flow content, not to route protection

  // Show loading spinner while checking authentication
  if (isLoading) {
    return fallback || <LoadingSpinner message="Verificando autenticación..." />;
  }

  // If route doesn't require auth, render children
  if (route && !route.requiresAuth) {
    return <>{children}</>;
  }

  // If user has access (authenticated OR demo mode), allow access
  if (hasAccess) {
    return <>{children}</>;
  }

  // If not authenticated and route requires auth, redirect to login
  if (!isAuthenticated) {
    const redirectPath = redirectTo || ROUTES.LOGIN;
    const returnUrl = location.pathname + location.search;

    return (
      <Navigate
        to={`${redirectPath}?returnUrl=${encodeURIComponent(returnUrl)}`}
        replace
      />
    );
  }

  // If no route config is provided, just check authentication
  if (!route) {
    return <>{children}</>;
  }

  // CRITICAL: If tenant access is still loading (undefined vs null), show loading state
  // This prevents showing "unauthorized" during the async load of tenant permissions
  const isTenantAccessLoading = currentTenant && currentTenantAccess === undefined;

  if (isTenantAccessLoading) {
    console.log('⏳ [ProtectedRoute] Waiting for tenant access to load...', {
      hasTenant: !!currentTenant,
      tenantId: currentTenant?.id,
      accessIsUndefined: currentTenantAccess === undefined
    });
    return fallback || <LoadingSpinner message="Cargando permisos..." />;
  }

  // Get user roles and permissions
  const globalUserRoles = user?.role ? [user.role] : [];
  const tenantRole = currentTenantAccess?.role;
  const tenantRoles = tenantRole ? [tenantRole] : [];

  // Combine global and tenant roles for comprehensive access control
  const allUserRoles = [...globalUserRoles, ...tenantRoles];
  const tenantPermissions = currentTenantAccess?.permissions || [];

  // Check if user can access this route
  const canAccess = canAccessRoute(route, isAuthenticated, allUserRoles, tenantPermissions);

  console.log('🔐 [ProtectedRoute] Access check:', {
    route: route.path,
    canAccess,
    globalUserRoles,
    tenantRoles,
    allUserRoles,
    tenantPermissions,
    currentTenantAccess
  });

  if (!canAccess) {
    // Check if it's a permission issue or role issue
    const hasRequiredRoles = !route.requiredRoles ||
      route.requiredRoles.some(role => allUserRoles.includes(role as string));

    console.error('❌ [ProtectedRoute] Access denied:', {
      route: route.path,
      hasRequiredRoles,
      requiredRoles: route.requiredRoles,
      userRoles: allUserRoles
    });

    if (!hasRequiredRoles) {
      return <UnauthorizedPage />;
    } else {
      return <ForbiddenPage />;
    }
  }

  // User has access, render the protected content
  return <>{children}</>;
};

// Higher-order component for route protection
export const withProtectedRoute = <P extends object>(
  Component: React.ComponentType<P>,
  route: RouteConfig,
  options?: {
    fallback?: React.ReactNode;
    redirectTo?: string;
  }
) => {
  const ProtectedComponent = (props: P) => (
    <ProtectedRoute 
      route={route} 
      fallback={options?.fallback}
      redirectTo={options?.redirectTo}
    >
      <Component {...props} />
    </ProtectedRoute>
  );

  ProtectedComponent.displayName = `withProtectedRoute(${Component.displayName || Component.name})`;
  
  return ProtectedComponent;
};

// Hook for checking route access
export const useRouteAccess = (route: RouteConfig) => {
  const user = useAuthUser();
  const isAuthenticated = useIsAuthenticated();
  const isLoading = useAuthLoading();
  const currentTenantAccess = useCurrentTenantAccess();

  const globalUserRoles = user?.role ? [user.role as string] : [];
  const tenantRole = currentTenantAccess?.role;
  const tenantRoles = tenantRole ? [tenantRole as string] : [];
  const allUserRoles = [...globalUserRoles, ...tenantRoles];
  const tenantPermissions = currentTenantAccess?.permissions || [];

  const canAccess = canAccessRoute(route, isAuthenticated, allUserRoles, tenantPermissions);

  return {
    canAccess,
    isLoading,
    isAuthenticated,
    globalUserRoles,
    tenantRoles,
    allUserRoles,
    tenantPermissions,
    currentTenantAccess,
    hasRequiredRoles: !route.requiredRoles || 
      route.requiredRoles.some(role => allUserRoles.includes(role as string)),
    hasRequiredPermissions: !route.requiredPermissions || 
      route.requiredPermissions.every(permission => tenantPermissions.includes(permission)),
  };
};

// Component for conditionally rendering content based on permissions
interface ConditionalRenderProps {
  children: React.ReactNode;
  requiredPermissions?: string[];
  requiredRoles?: string[];
  requireAll?: boolean; // If true, requires ALL permissions/roles, otherwise ANY
  fallback?: React.ReactNode;
}

export const ConditionalRender: React.FC<ConditionalRenderProps> = ({
  children,
  requiredPermissions = [],
  requiredRoles = [],
  requireAll = true,
  fallback = null,
}) => {
  const user = useAuthUser();
  const isAuthenticated = useIsAuthenticated();
  const currentTenantAccess = useCurrentTenantAccess();

  if (!isAuthenticated || !user) {
    return <>{fallback}</>;
  }

  const globalUserRoles = user.role ? [user.role as string] : [];
  const tenantRole = currentTenantAccess?.role;
  const tenantRoles = tenantRole ? [tenantRole as string] : [];
  const allUserRoles = [...globalUserRoles, ...tenantRoles];
  const tenantPermissions = currentTenantAccess?.permissions || [];

  // Check roles
  let hasRoles = true;
  if (requiredRoles.length > 0) {
    if (requireAll) {
      hasRoles = requiredRoles.every(role => allUserRoles.includes(role as string));
    } else {
      hasRoles = requiredRoles.some(role => allUserRoles.includes(role as string));
    }
  }

  // Check permissions
  let hasPermissions = true;
  if (requiredPermissions.length > 0) {
    if (requireAll) {
      hasPermissions = requiredPermissions.every(permission => tenantPermissions.includes(permission));
    } else {
      hasPermissions = requiredPermissions.some(permission => tenantPermissions.includes(permission));
    }
  }

  if (hasRoles && hasPermissions) {
    return <>{children}</>;
  }

  return <>{fallback}</>;
};

// Route guard for admin-only routes (global admin or tenant owner/admin)
// Uses unified permission system
export const AdminRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const user = useAuthUser();
  const tenantAccess = useCurrentTenantAccess();

  // Check using unified permission system
  const hasAccess = checkCombinedPermission(user as User | undefined, tenantAccess as TenantAccess | undefined, {
    globalRoles: ['admin', 'super_admin'],
    tenantRoles: ['owner', 'admin']
  });

  return hasAccess ? <>{children}</> : <UnauthorizedPage />;
};

// Route guard for manager-level routes (global admin/manager or tenant admin/owner)
// Uses unified permission system
export const ManagerRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const user = useAuthUser();
  const tenantAccess = useCurrentTenantAccess();

  // Check using unified permission system
  const hasAccess = checkCombinedPermission(user as User | undefined, tenantAccess as TenantAccess | undefined, {
    globalRoles: ['admin', 'super_admin', 'manager'],
    tenantRoles: ['owner', 'admin', 'member']
  });

  return hasAccess ? <>{children}</> : <UnauthorizedPage />;
};

// Route guard for tenant owner-only routes
// Uses unified permission system
export const OwnerRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const user = useAuthUser();
  const tenantAccess = useCurrentTenantAccess();

  // Check using unified permission system
  const hasAccess = checkCombinedPermission(user as User | undefined, tenantAccess as TenantAccess | undefined, {
    globalRoles: ['super_admin'],
    tenantRoles: ['owner']
  });

  return hasAccess ? <>{children}</> : <UnauthorizedPage />;
};