'use client';

import { useEffect, useRef, useState, useCallback } from 'react';
import { useSession } from 'next-auth/react';

interface ResponsiveIframeProps {
  src: string;
  className?: string;
  allow?: string;
  style?: React.CSSProperties;
  /** Enable SSO token forwarding for this iframe */
  enableSso?: boolean;
  /** Service name for SSO (e.g., 'nextcloud', 'rocketchat') */
  serviceName?: string;
}

// Known service domains for automatic SSO detection
const SSO_SERVICE_DOMAINS: Record<string, string> = {
  'espace.slm-lab.net': 'nextcloud',
  'parole.slm-lab.net': 'rocketchat',
  'apprendre.slm-lab.net': 'moodle',
  'artlab.slm-lab.net': 'penpot',
  'alma.slm-lab.net': 'openwebui',
  'agilite.slm-lab.net': 'leantime',
  'chapitre.slm-lab.net': 'bookstack',
  'vision.slm-lab.net': 'jitsi',
  'lemessage.slm-lab.net': 'listmonk',
};

/**
 * Detect service name from URL
 */
function detectServiceFromUrl(url: string): string | undefined {
  try {
    const urlObj = new URL(url);
    return SSO_SERVICE_DOMAINS[urlObj.hostname];
  } catch {
    return undefined;
  }
}

export function ResponsiveIframe({ 
  src, 
  className = '', 
  allow, 
  style,
  enableSso = true,
  serviceName: propServiceName,
}: ResponsiveIframeProps) {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const { data: session } = useSession();
  const [isRefreshing, setIsRefreshing] = useState(false);
  const [iframeSrc, setIframeSrc] = useState<string>('');
  const [hasTriedRefresh, setHasTriedRefresh] = useState(false);
  const [ssoStatus, setSsoStatus] = useState<'pending' | 'success' | 'fallback' | 'error'>('pending');

  // Detect service name from URL if not provided
  const serviceName = propServiceName || detectServiceFromUrl(src);

  /**
   * Attempt to get an SSO-authenticated URL from our API
   */
  const getSsoAuthenticatedUrl = useCallback(async (originalUrl: string): Promise<string> => {
    if (!enableSso || !session?.accessToken) {
      return originalUrl;
    }

    try {
      // Try to get an authenticated URL from our SSO API
      const response = await fetch(`/api/auth/service-sso?url=${encodeURIComponent(originalUrl)}`, {
        method: 'GET',
        credentials: 'include',
      });

      if (response.ok) {
        const data = await response.json();
        if (data.success && data.url) {
          console.log(`[SSO] Got authenticated URL for ${serviceName || 'unknown service'}`);
          setSsoStatus('success');
          return data.url;
        }
      }
      
      console.warn('[SSO] Failed to get authenticated URL, using original');
      setSsoStatus('fallback');
      return originalUrl;
    } catch (error) {
      console.error('[SSO] Error getting authenticated URL:', error);
      setSsoStatus('error');
      return originalUrl;
    }
  }, [enableSso, session?.accessToken, serviceName]);

  // Refresh NextAuth session and get SSO URL before loading iframe
  useEffect(() => {
    // If no src, nothing to do
    if (!src) {
      return;
    }

    // Check if user just logged out - prevent refresh if logout is in progress
    const justLoggedOut = sessionStorage.getItem('just_logged_out') === 'true';
    const logoutCookie = document.cookie.split(';').some(c => c.trim().startsWith('logout_in_progress=true'));
    
    if (justLoggedOut || logoutCookie) {
      console.warn('Logout in progress, redirecting to sign-in instead of refreshing session');
      window.location.href = '/signin';
      return;
    }

    // If no session yet, wait for it (don't set src yet)
    if (!session) {
      return;
    }

    // If already tried refresh for this src, just set it
    if (hasTriedRefresh) {
      if (!iframeSrc) {
        setIframeSrc(src);
      }
      return;
    }

    // Ensure session has required tokens before proceeding
    if (!session.accessToken || !session.refreshToken) {
      console.warn('Session missing required tokens, redirecting to sign-in');
      window.location.href = '/signin';
      return;
    }

    const refreshSession = async () => {
      setIsRefreshing(true);
      setHasTriedRefresh(true);
      
      try {
        // Wait a bit to ensure NextAuth session is fully established
        await new Promise(resolve => setTimeout(resolve, 100));
        
        // Double-check logout flag before making the request
        const stillLoggedOut = sessionStorage.getItem('just_logged_out') === 'true';
        if (stillLoggedOut) {
          console.warn('Logout detected during refresh, aborting');
          window.location.href = '/signin';
          return;
        }
        
        // Call our API to refresh the Keycloak session
        // This ensures tokens are fresh and may help refresh Keycloak session cookies
        const response = await fetch('/api/auth/refresh-keycloak-session', {
          method: 'GET',
          credentials: 'include', // Include cookies
        });
        
        if (response.ok) {
          console.log('Session refreshed before loading iframe');
          
          // Try to get SSO-authenticated URL
          const authenticatedUrl = await getSsoAuthenticatedUrl(src);
          setIframeSrc(authenticatedUrl);
        } else {
          const errorData = await response.json().catch(() => ({}));
          
          // If session was invalidated, redirect to sign-in
          if (response.status === 401 && errorData.error === 'SessionInvalidated') {
            console.warn('Keycloak session invalidated, redirecting to sign-in');
            window.location.href = '/signin';
            return;
          }
          
          console.warn('Failed to refresh session, loading iframe anyway (may require login)');
          // Still try SSO, then fall back to original URL
          const authenticatedUrl = await getSsoAuthenticatedUrl(src);
          setIframeSrc(authenticatedUrl);
        }
      } catch (error) {
        console.error('Error refreshing session:', error);
        // On error, still try to load iframe with original URL
        setIframeSrc(src);
        setSsoStatus('error');
      } finally {
        setIsRefreshing(false);
      }
    };

    refreshSession();
  }, [session, src, hasTriedRefresh, iframeSrc, getSsoAuthenticatedUrl]);

  // Listen for messages from iframe applications (logout, auth requests)
  useEffect(() => {
    const handleMessage = async (event: MessageEvent) => {
      // Security: Only accept messages from known iframe origins
      const trustedOrigins = Object.keys(SSO_SERVICE_DOMAINS).map(domain => `https://${domain}`);
      const isFromTrustedOrigin = trustedOrigins.some(origin => event.origin.includes(origin.replace('https://', '')));
      
      if (!isFromTrustedOrigin && event.origin !== window.location.origin) {
        // Log but don't block - some services may have different origins
        console.debug('[Iframe] Message from unknown origin:', event.origin);
      }
      
      // Check if message is a data object
      if (event.data && typeof event.data === 'object') {
        // Handle logout request from iframe
        if (event.data.type === 'KEYCLOAK_LOGOUT' || event.data.type === 'LOGOUT') {
          console.log('Received logout request from iframe, triggering dashboard logout');
          
          // Mark logout in progress
          sessionStorage.setItem('just_logged_out', 'true');
          document.cookie = 'logout_in_progress=true; path=/; max-age=60';
          
          // Trigger dashboard logout
          if (session?.idToken) {
            const keycloakIssuer = process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER;
            if (keycloakIssuer) {
              const keycloakLogoutUrl = new URL(
                `${keycloakIssuer}/protocol/openid-connect/logout`
              );
              keycloakLogoutUrl.searchParams.append(
                'post_logout_redirect_uri',
                window.location.origin + '/signin?logout=true'
              );
              keycloakLogoutUrl.searchParams.append(
                'id_token_hint',
                session.idToken
              );
              window.location.replace(keycloakLogoutUrl.toString());
            }
          } else {
            // Fallback: redirect to signin
            window.location.replace('/signin?logout=true');
          }
        }
        
        // Handle RocketChat auth request
        if (event.data.type === 'rocketchat.getAuthToken' || event.data.event === 'call-token-auth') {
          console.log('[RocketChat] Auth token requested by iframe');
          if (session?.accessToken && iframeRef.current?.contentWindow) {
            // Send auth token to RocketChat
            iframeRef.current.contentWindow.postMessage({
              event: 'login-with-token',
              loginToken: session.accessToken,
            }, event.origin);
          }
        }
        
        // Handle generic SSO auth request from any iframe
        if (event.data.type === 'SSO_AUTH_REQUEST') {
          console.log('[SSO] Auth request from iframe:', event.origin);
          if (session?.accessToken && iframeRef.current?.contentWindow) {
            iframeRef.current.contentWindow.postMessage({
              type: 'SSO_AUTH_RESPONSE',
              accessToken: session.accessToken,
              userId: session.user?.id,
              email: session.user?.email,
              username: session.user?.username,
            }, event.origin);
          }
        }
      }
    };

    window.addEventListener('message', handleMessage);
    return () => {
      window.removeEventListener('message', handleMessage);
    };
  }, [session]);

  useEffect(() => {
    const iframe = iframeRef.current;
    if (!iframe || !iframeSrc) return;

    const calculateHeight = () => {
      const pageY = (elem: HTMLElement): number => {
        return elem.offsetParent ? 
          (elem.offsetTop + pageY(elem.offsetParent as HTMLElement)) : 
          elem.offsetTop;
      };

      const height = document.documentElement.clientHeight;
      const iframeY = pageY(iframe);
      const newHeight = Math.max(0, height - iframeY);
      iframe.style.height = `${newHeight}px`;
    };

    const handleHashChange = () => {
      if (window.location.hash && window.location.hash.length && iframe.src) {
        const iframeURL = new URL(iframe.src);
        iframeURL.hash = window.location.hash;
        iframe.src = iframeURL.toString();
      }
    };

    // Initial setup
    calculateHeight();
    handleHashChange();

    // Event listeners
    window.addEventListener('resize', calculateHeight);
    window.addEventListener('hashchange', handleHashChange);
    iframe.addEventListener('load', calculateHeight);

    // Cleanup
    return () => {
      window.removeEventListener('resize', calculateHeight);
      window.removeEventListener('hashchange', handleHashChange);
      iframe.removeEventListener('load', calculateHeight);
    };
  }, [iframeSrc]);

  // Send auth token to RocketChat iframe after it loads
  const handleIframeLoad = useCallback(() => {
    if (!iframeRef.current || !session?.accessToken) return;
    
    const iframe = iframeRef.current;
    const iframeUrl = iframe.src;
    
    // Check if this is RocketChat and send auth token
    if (serviceName === 'rocketchat' && iframe.contentWindow) {
      try {
        console.log('[RocketChat] Sending auth token to iframe');
        iframe.contentWindow.postMessage({
          externalCommand: 'login-with-token',
          token: session.accessToken,
        }, new URL(iframeUrl).origin);
      } catch (error) {
        console.warn('[RocketChat] Could not send auth token:', error);
      }
    }
  }, [session?.accessToken, serviceName]);

  return (
    <>
      {isRefreshing && (
        <div className="flex items-center justify-center w-full h-full absolute bg-black/50 z-10">
          <div className="text-center bg-white p-4 rounded-lg shadow-xl">
            <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500 mx-auto mb-4"></div>
            <p className="text-gray-600">
              {ssoStatus === 'pending' && 'Connexion SSO en cours...'}
              {ssoStatus === 'success' && 'Authentification réussie...'}
              {ssoStatus === 'fallback' && 'Chargement...'}
              {ssoStatus === 'error' && 'Chargement (connexion manuelle peut être requise)...'}
            </p>
            {serviceName && (
              <p className="text-xs text-gray-400 mt-2">
                Service: {serviceName}
              </p>
            )}
          </div>
        </div>
      )}
      
      <iframe
        ref={iframeRef}
        id="myFrame"
        src={iframeSrc || ''}
        className={`w-full border-none ${className}`}
        style={{
          display: iframeSrc ? 'block' : 'none',
          width: '100%',
          height: '100%',
          ...style
        }}
        allow={allow}
        allowFullScreen
        onLoad={handleIframeLoad}
      />
      
      {/* Show placeholder while waiting for session */}
      {!iframeSrc && !isRefreshing && (
        <div className="flex items-center justify-center w-full h-full bg-gray-900">
          <div className="text-center">
            <div className="animate-pulse">
              <div className="h-8 w-32 bg-gray-700 rounded mx-auto mb-4"></div>
              <div className="h-4 w-48 bg-gray-700 rounded mx-auto"></div>
            </div>
            <p className="text-gray-400 mt-4">En attente de la session...</p>
          </div>
        </div>
      )}
    </>
  );
} 