import React, {
  useState,
  useEffect,
  useCallback,
  useMemo,
  useRef,
} from "react";
import {
  DeviceType,
  useDeviceDetection,
  DeviceConditional,
} from "./device-detector";
import {
  useRealTimeDeviceMonitor,
  ExtendedDeviceInfo,
} from "./real-time-device-monitor";

// Import the existing chat components
// Note: These will be lazy-loaded for better performance
const DesktopChatModal = React.lazy(() =>
  import("./desktop-chat-modal").then((module) => ({
    default: module.DesktopChatModal,
  }))
);
const MobileFullscreenChat = React.lazy(() =>
  import("./mobile-fullscreen-chat").then((module) => ({
    default: module.MobileFullscreenChat,
  }))
);
const FloatingChatButton = React.lazy(() =>
  import("./floating-chat-button").then((module) => ({
    default: module.FloatingChatButton,
  }))
);

// Router configuration interface
export interface AdaptiveChatRouterConfig {
  // Component selection strategy
  strategy: "device-type" | "screen-size" | "hybrid" | "user-preference";

  // Breakpoints for screen-size strategy
  mobileMaxWidth: number;
  tabletMaxWidth: number;

  // Behavior options
  allowUserOverride: boolean;
  persistUserPreference: boolean;
  enableTransitions: boolean;

  // Performance options
  enableLazyLoading: boolean;
  preloadComponents: boolean;
  enableMemoryManagement: boolean;

  // Debug and logging
  enableDebugMode: boolean;
  enablePerformanceLogging: boolean;
}

const DEFAULT_CONFIG: AdaptiveChatRouterConfig = {
  strategy: "hybrid",
  mobileMaxWidth: 768,
  tabletMaxWidth: 1024,
  allowUserOverride: true,
  persistUserPreference: true,
  enableTransitions: true,
  enableLazyLoading: true,
  preloadComponents: false,
  enableMemoryManagement: true,
  enableDebugMode: false,
  enablePerformanceLogging: false,
};

// Chat interface types
export enum ChatInterface {
  DESKTOP = "desktop",
  MOBILE = "mobile",
  TABLET = "tablet",
  AUTO = "auto",
}

export interface ChatState {
  isOpen: boolean;
  currentInterface: ChatInterface;
  requestedInterface?: ChatInterface;
  isTransitioning: boolean;
  sessionId: string;
  lastInteraction: number;
}

// Router context for child components
interface AdaptiveChatRouterContextType {
  chatState: ChatState;
  deviceInfo: ExtendedDeviceInfo;
  config: AdaptiveChatRouterConfig;
  openChat: (preferredInterface?: ChatInterface) => void;
  closeChat: () => void;
  switchInterface: (chatInterface: ChatInterface) => void;
  isInterfaceSupported: (chatInterface: ChatInterface) => boolean;
}

const AdaptiveChatRouterContext = React.createContext<
  AdaptiveChatRouterContextType | undefined
>(undefined);

// Custom hook to use the router context
export const useAdaptiveChatRouter = (): AdaptiveChatRouterContextType => {
  const context = React.useContext(AdaptiveChatRouterContext);
  if (context === undefined) {
    throw new Error(
      "useAdaptiveChatRouter must be used within an AdaptiveChatRouterProvider"
    );
  }
  return context;
};

// Utility functions
const generateSessionId = (): string => {
  return `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
};

const getStorageKey = (key: string, sessionId?: string): string => {
  return sessionId ? `agentc_chat_${key}_${sessionId}` : `agentc_chat_${key}`;
};

const getUserPreference = (): ChatInterface | null => {
  if (typeof window === "undefined") return null;
  try {
    const stored = localStorage.getItem(
      getStorageKey("user_interface_preference")
    );
    return (stored as ChatInterface) || null;
  } catch {
    return null;
  }
};

const setUserPreference = (chatInterface: ChatInterface): void => {
  if (typeof window === "undefined") return;
  try {
    localStorage.setItem(
      getStorageKey("user_interface_preference"),
      chatInterface
    );
  } catch {
    // Silently fail if localStorage is not available
  }
};

// Interface determination logic
const determineOptimalInterface = (
  deviceInfo: ExtendedDeviceInfo,
  config: AdaptiveChatRouterConfig,
  userPreference?: ChatInterface
): ChatInterface => {
  // User preference takes priority if allowed
  if (
    config.allowUserOverride &&
    userPreference &&
    userPreference !== ChatInterface.AUTO
  ) {
    return userPreference;
  }

  // Strategy-based determination
  switch (config.strategy) {
    case "device-type":
      return determineByDeviceType(deviceInfo);

    case "screen-size":
      return determineByScreenSize(deviceInfo, config);

    case "user-preference":
      return userPreference || ChatInterface.AUTO;

    case "hybrid":
    default:
      return determineByHybrid(deviceInfo, config);
  }
};

const determineByDeviceType = (
  deviceInfo: ExtendedDeviceInfo
): ChatInterface => {
  switch (deviceInfo.type) {
    case DeviceType.MOBILE:
      return ChatInterface.MOBILE;
    case DeviceType.TABLET:
      return ChatInterface.MOBILE; // Tablets use mobile interface for better touch experience
    case DeviceType.DESKTOP:
    default:
      return ChatInterface.DESKTOP;
  }
};

const determineByScreenSize = (
  deviceInfo: ExtendedDeviceInfo,
  config: AdaptiveChatRouterConfig
): ChatInterface => {
  const { screenWidth } = deviceInfo;

  if (screenWidth <= config.mobileMaxWidth) {
    return ChatInterface.MOBILE;
  }

  if (screenWidth <= config.tabletMaxWidth && deviceInfo.isTouchDevice) {
    return ChatInterface.MOBILE;
  }

  return ChatInterface.DESKTOP;
};

const determineByHybrid = (
  deviceInfo: ExtendedDeviceInfo,
  config: AdaptiveChatRouterConfig
): ChatInterface => {
  // Combine device type and screen size analysis
  const deviceTypeResult = determineByDeviceType(deviceInfo);
  const screenSizeResult = determineByScreenSize(deviceInfo, config);

  // Special cases for hybrid approach
  if (
    deviceInfo.isTouchDevice &&
    deviceInfo.screenWidth <= config.tabletMaxWidth
  ) {
    return ChatInterface.MOBILE;
  }

  // If both methods agree, use that
  if (deviceTypeResult === screenSizeResult) {
    return deviceTypeResult;
  }

  // Fallback: prefer mobile for touch devices, desktop otherwise
  return deviceInfo.isTouchDevice
    ? ChatInterface.MOBILE
    : ChatInterface.DESKTOP;
};

// Performance monitoring
const usePerformanceMonitoring = (config: AdaptiveChatRouterConfig) => {
  const metricsRef = useRef({
    componentSwitches: 0,
    averageSwitchTime: 0,
    switchTimes: [] as number[],
    memoryUsage: 0,
    lastGC: Date.now(),
  });

  const logMetric = useCallback(
    (metric: string, value: number) => {
      if (config.enablePerformanceLogging) {
        console.log(`[AdaptiveChatRouter] ${metric}:`, value);
      }
    },
    [config.enablePerformanceLogging]
  );

  const recordSwitch = useCallback(
    (startTime: number) => {
      const switchTime = Date.now() - startTime;
      const metrics = metricsRef.current;

      metrics.componentSwitches++;
      metrics.switchTimes.push(switchTime);

      // Keep only last 10 switch times
      if (metrics.switchTimes.length > 10) {
        metrics.switchTimes = metrics.switchTimes.slice(-10);
      }

      metrics.averageSwitchTime =
        metrics.switchTimes.reduce((a, b) => a + b, 0) /
        metrics.switchTimes.length;

      logMetric("Component Switch Time", switchTime);
      logMetric("Average Switch Time", metrics.averageSwitchTime);
    },
    [logMetric]
  );

  return { recordSwitch, metrics: metricsRef.current };
};

// Main router component
interface AdaptiveChatRouterProps {
  children?: React.ReactNode;
  config?: Partial<AdaptiveChatRouterConfig>;
  onInterfaceChange?: (
    oldInterface: ChatInterface,
    newInterface: ChatInterface
  ) => void;
  onChatStateChange?: (chatState: ChatState) => void;
}

export const AdaptiveChatRouter: React.FC<AdaptiveChatRouterProps> = ({
  children,
  config: userConfig = {},
  onInterfaceChange,
  onChatStateChange,
}) => {
  const config = useMemo(
    () => ({ ...DEFAULT_CONFIG, ...userConfig }),
    [userConfig]
  );
  const deviceInfo = useRealTimeDeviceMonitor();
  const { recordSwitch } = usePerformanceMonitoring(config);

  // State management
  const [chatState, setChatState] = useState<ChatState>(() => ({
    isOpen: false,
    currentInterface: ChatInterface.AUTO,
    isTransitioning: false,
    sessionId: generateSessionId(),
    lastInteraction: Date.now(),
  }));

  const [userPreference, setUserPreferenceState] =
    useState<ChatInterface | null>(() =>
      config.persistUserPreference ? getUserPreference() : null
    );

  // Determine optimal interface
  const optimalInterface = useMemo(() => {
    return determineOptimalInterface(
      deviceInfo,
      config,
      userPreference || undefined
    );
  }, [deviceInfo, config, userPreference]);

  // Update interface when optimal interface changes
  useEffect(() => {
    if (
      optimalInterface !== chatState.currentInterface &&
      chatState.currentInterface !== ChatInterface.AUTO
    ) {
      const startTime = Date.now();

      setChatState((prev) => ({
        ...prev,
        isTransitioning: true,
      }));

      // Transition delay for smooth UX
      const transitionDelay = config.enableTransitions ? 300 : 0;

      setTimeout(() => {
        setChatState((prev) => {
          const newState = {
            ...prev,
            currentInterface: optimalInterface,
            isTransitioning: false,
            lastInteraction: Date.now(),
          };

          onInterfaceChange?.(prev.currentInterface, optimalInterface);
          recordSwitch(startTime);

          return newState;
        });
      }, transitionDelay);
    } else if (chatState.currentInterface === ChatInterface.AUTO) {
      // Initialize with optimal interface
      setChatState((prev) => ({
        ...prev,
        currentInterface: optimalInterface,
      }));
    }
  }, [
    optimalInterface,
    chatState.currentInterface,
    config.enableTransitions,
    onInterfaceChange,
    recordSwitch,
  ]);

  // Interface support validation
  const isInterfaceSupported = useCallback(
    (chatInterface: ChatInterface): boolean => {
      switch (chatInterface) {
        case ChatInterface.DESKTOP:
          return !deviceInfo.isMobile; // Desktop requires non-mobile device
        case ChatInterface.MOBILE:
          return true; // Mobile interface works on all devices
        case ChatInterface.TABLET:
          return deviceInfo.isTablet;
        case ChatInterface.AUTO:
          return true;
        default:
          return false;
      }
    },
    [deviceInfo]
  );

  // Chat control functions
  const openChat = useCallback(
    (preferredInterface?: ChatInterface) => {
      let targetInterface = preferredInterface || optimalInterface;

      // Validate interface support
      if (!isInterfaceSupported(targetInterface)) {
        targetInterface = optimalInterface;
      }

      setChatState((prev) => ({
        ...prev,
        isOpen: true,
        currentInterface: targetInterface,
        requestedInterface: preferredInterface,
        lastInteraction: Date.now(),
      }));
    },
    [optimalInterface, isInterfaceSupported]
  );

  const closeChat = useCallback(() => {
    setChatState((prev) => ({
      ...prev,
      isOpen: false,
      lastInteraction: Date.now(),
    }));
  }, []);

  const switchInterface = useCallback(
    (chatInterface: ChatInterface) => {
      if (!isInterfaceSupported(chatInterface)) {
        console.warn(
          `Interface ${chatInterface} is not supported on this device`
        );
        return;
      }

      // Update user preference if persistence is enabled
      if (
        config.persistUserPreference &&
        chatInterface !== ChatInterface.AUTO
      ) {
        setUserPreference(chatInterface);
        setUserPreferenceState(chatInterface);
      }

      setChatState((prev) => ({
        ...prev,
        currentInterface: chatInterface,
        requestedInterface: chatInterface,
        lastInteraction: Date.now(),
      }));
    },
    [isInterfaceSupported, config.persistUserPreference]
  );

  // Notify parent about chat state changes
  useEffect(() => {
    onChatStateChange?.(chatState);
  }, [chatState, onChatStateChange]);

  // Context value
  const contextValue: AdaptiveChatRouterContextType = {
    chatState,
    deviceInfo,
    config,
    openChat,
    closeChat,
    switchInterface,
    isInterfaceSupported,
  };

  return (
    <AdaptiveChatRouterContext.Provider value={contextValue}>
      {children}
      <ChatInterfaceRenderer />
      {config.enableDebugMode && <RouterDebugPanel />}
    </AdaptiveChatRouterContext.Provider>
  );
};

// Chat interface renderer component
const ChatInterfaceRenderer: React.FC = () => {
  const { chatState, config } = useAdaptiveChatRouter();

  if (!chatState.isOpen) return null;

  const LoadingSpinner = () => (
    <div
      style={{
        position: "fixed",
        top: "50%",
        left: "50%",
        transform: "translate(-50%, -50%)",
        zIndex: 9999,
      }}
    >
      <div
        style={{
          width: "40px",
          height: "40px",
          border: "4px solid #f3f3f3",
          borderTop: "4px solid #3498db",
          borderRadius: "50%",
          animation: "spin 1s linear infinite",
        }}
      />
      <style>
        {`
          @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
          }
        `}
      </style>
    </div>
  );

  if (config.enableLazyLoading) {
    return (
      <React.Suspense fallback={<LoadingSpinner />}>
        <DeviceConditional
          mobile={
            chatState.currentInterface === ChatInterface.MOBILE ? (
              <MobileFullscreenChat />
            ) : null
          }
          desktop={
            chatState.currentInterface === ChatInterface.DESKTOP ? (
              <DesktopChatModal />
            ) : null
          }
          tablet={
            chatState.currentInterface === ChatInterface.TABLET ? (
              <MobileFullscreenChat />
            ) : null
          }
        />
      </React.Suspense>
    );
  }

  // Non-lazy loading fallback
  return (
    <DeviceConditional
      mobile={
        chatState.currentInterface === ChatInterface.MOBILE ? (
          <div>Mobile Chat Component</div>
        ) : null
      }
      desktop={
        chatState.currentInterface === ChatInterface.DESKTOP ? (
          <div>Desktop Chat Component</div>
        ) : null
      }
      tablet={
        chatState.currentInterface === ChatInterface.TABLET ? (
          <div>Tablet Chat Component</div>
        ) : null
      }
    />
  );
};

// Debug panel component
const RouterDebugPanel: React.FC = () => {
  const { chatState, deviceInfo, config } = useAdaptiveChatRouter();

  if (process.env.NODE_ENV === "production") return null;

  return (
    <div
      style={{
        position: "fixed",
        bottom: 10,
        left: 10,
        background: "rgba(0, 0, 0, 0.9)",
        color: "white",
        padding: "10px",
        borderRadius: "5px",
        fontSize: "12px",
        fontFamily: "monospace",
        zIndex: 9999,
        maxWidth: "350px",
        maxHeight: "200px",
        overflow: "auto",
      }}
    >
      <div style={{ fontWeight: "bold", marginBottom: "5px" }}>
        Adaptive Chat Router Debug
      </div>
      <div>Strategy: {config.strategy}</div>
      <div>Current Interface: {chatState.currentInterface}</div>
      <div>Requested Interface: {chatState.requestedInterface || "None"}</div>
      <div>Chat Open: {chatState.isOpen ? "Yes" : "No"}</div>
      <div>Device Type: {deviceInfo.type}</div>
      <div>Touch Device: {deviceInfo.isTouchDevice ? "Yes" : "No"}</div>
      <div>
        Screen: {deviceInfo.screenWidth}x{deviceInfo.screenHeight}
      </div>
      <div>Transitioning: {chatState.isTransitioning ? "Yes" : "No"}</div>
    </div>
  );
};

// Floating button wrapper with adaptive behavior
interface AdaptiveFloatingChatButtonProps {
  onToggle?: (isOpen: boolean) => void;
  className?: string;
  style?: React.CSSProperties;
}

export const AdaptiveFloatingChatButton: React.FC<
  AdaptiveFloatingChatButtonProps
> = ({ onToggle, className, style }) => {
  const { openChat, closeChat, chatState } = useAdaptiveChatRouter();

  const handleToggle = useCallback(() => {
    if (chatState.isOpen) {
      closeChat();
      onToggle?.(false);
    } else {
      openChat();
      onToggle?.(true);
    }
  }, [chatState.isOpen, openChat, closeChat, onToggle]);

  return (
    <React.Suspense fallback={null}>
      <FloatingChatButton
        onClick={handleToggle}
        className={className}
        style={style}
      />
    </React.Suspense>
  );
};

export default AdaptiveChatRouter;
