// contexts/WindowManagerContext.tsx

'use client';

import React, { createContext, useContext, useState, useEffect } from 'react';

type WindowData = {
  name: string;
  Component: React.ComponentType;
  windowProps: {
    width?: string;
    height?: string;
  };
};

type WindowState = {
  visible: boolean;
  minimized: boolean;
  maximized: boolean;
  width: number;
  height: number;
  x: number;
  y: number;
  prevWidth?: number;
  prevHeight?: number;
  prevX?: number;
  prevY?: number;
};

type WindowManagerContextType = {
  windows: { [key: string]: WindowData };
  windowStates: { [key: string]: WindowState };
  openWindow: (name: string) => void;
  closeWindow: (name: string) => void;
  minimizeWindow: (name: string) => void;
  restoreWindow: (name: string) => void;
  maximizeWindow: (name: string) => void;
  updateWindowState: (name: string, newState: Partial<WindowState>) => void;
};

const WindowManagerContext = createContext<WindowManagerContextType | undefined>(undefined);

export const useWindowManager = () => {
  const context = useContext(WindowManagerContext);
  if (!context) {
    throw new Error('useWindowManager must be used within a WindowManagerProvider');
  }
  return context;
};

export const WindowManagerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [windows, setWindows] = useState<{ [key: string]: WindowData }>({});
  const [windowStates, setWindowStates] = useState<{ [key: string]: WindowState }>({});

  useEffect(() => {
    // Dynamically import window components
    const importWindows = async () => {
      const windowsContext = require.context('../windows', false, /\.tsx$/);
      const windowFiles = windowsContext.keys();

      const windowsDataPromises = windowFiles.map(async (file: string, index: number) => {
        const mod = await windowsContext(file);
        const name = file.replace('./', '').replace('.tsx', '');
        const Component = mod.default;
        const windowProps = mod.windowProps || {};

        // Parse initial size
        const width = windowProps.width
          ? parseSize(windowProps.width, 'width')
          : 0.35 * window.innerWidth;
        const height = windowProps.height
          ? parseSize(windowProps.height, 'height')
          : 0.2 * window.innerHeight;

        const windowData: WindowData = { name, Component, windowProps };
        const windowState: WindowState = {
          visible: true,
          minimized: false,
          maximized: false,
          width,
          height,
          x: 100 + index * 50,
          y: 100 + index * 50,
        };

        return { windowData, windowState };
      });

      const windowsDataArray = await Promise.all(windowsDataPromises);

      const newWindows: { [key: string]: WindowData } = {};
      const newWindowStates: { [key: string]: WindowState } = {};

      windowsDataArray.forEach(({ windowData, windowState }) => {
        newWindows[windowData.name] = windowData;
        newWindowStates[windowData.name] = windowState;
      });

      setWindows(newWindows);
      setWindowStates(newWindowStates);
    };

    importWindows();
  }, []);

  const openWindow = (name: string) => {
    setWindowStates((prev) => ({
      ...prev,
      [name]: {
        ...prev[name],
        visible: true,
        minimized: false,
      },
    }));
  };

  const closeWindow = (name: string) => {
    setWindowStates((prev) => ({
      ...prev,
      [name]: {
        ...prev[name],
        visible: false,
        minimized: false,
      },
    }));
  };

  const minimizeWindow = (name: string) => {
    setWindowStates((prev) => ({
      ...prev,
      [name]: {
        ...prev[name],
        minimized: true,
        visible: false,
      },
    }));
  };

  const restoreWindow = (name: string) => {
    setWindowStates((prev) => ({
      ...prev,
      [name]: {
        ...prev[name],
        minimized: false,
        visible: true,
      },
    }));
  };

  const maximizeWindow = (name: string) => {
    setWindowStates((prev) => {
      const state = prev[name];
      const isMaximized = !state.maximized;

      if (isMaximized) {
        // Store previous size and position
        const prevSizePosition = {
          prevWidth: state.width,
          prevHeight: state.height,
          prevX: state.x,
          prevY: state.y,
        };

        return {
          ...prev,
          [name]: {
            ...state,
            maximized: true,
            ...prevSizePosition,
            x: 10,
            y: 10,
            width: window.innerWidth - 20,
            height: window.innerHeight - 20,
          },
        };
      } else {
        // Restore previous size and position
        return {
          ...prev,
          [name]: {
            ...state,
            maximized: false,
            width: state.prevWidth || state.width,
            height: state.prevHeight || state.height,
            x: state.prevX || state.x,
            y: state.prevY || state.y,
          },
        };
      }
    });
  };

  const updateWindowState = (name: string, newState: Partial<WindowState>) => {
    setWindowStates((prev) => ({
      ...prev,
      [name]: {
        ...prev[name],
        ...newState,
      },
    }));
  };

  // Helper function to parse size from string to number (pixels)
  function parseSize(size: string, dimension: 'width' | 'height'): number {
    if (typeof window === 'undefined') return 400; // Default size for SSR
    if (size.endsWith('%')) {
      const percentage = parseFloat(size) / 100;
      if (dimension === 'width') {
        return percentage * window.innerWidth;
      } else {
        return percentage * window.innerHeight;
      }
    } else if (size.endsWith('px')) {
      return parseFloat(size);
    } else {
      // Default fallback
      return dimension === 'width' ? 400 : 300;
    }
  }

  return (
    <WindowManagerContext.Provider
      value={{
        windows,
        windowStates,
        openWindow,
        closeWindow,
        minimizeWindow,
        restoreWindow,
        maximizeWindow,
        updateWindowState,
      }}
    >
      {children}
    </WindowManagerContext.Provider>
  );
};

AND:

// app/DraggableWindows.tsx

'use client';

import React from 'react';
import { Rnd } from 'react-rnd';
import { AiOutlineClose, AiOutlineMinus, AiOutlineFullscreen } from 'react-icons/ai';
import { useWindowManager } from '../contexts/WindowManagerContext';

const DraggableWindows: React.FC = () => {
  const {
    windows,
    windowStates,
    closeWindow,
    minimizeWindow,
    maximizeWindow,
    updateWindowState,
  } = useWindowManager();

  return (
    <div className="w-full h-full fixed top-0 left-0">
      {Object.keys(windows).map((name) => {
        const { Component } = windows[name];
        const state = windowStates[name];

        if (!Component || !state?.visible || state.minimized) return null;

        return (
          <Rnd
            key={name}
            size={{ width: state.width, height: state.height }}
            position={{ x: state.x, y: state.y }}
            onDragStop={(e, d) =>
              updateWindowState(name, { x: d.x, y: d.y })
            }
            onResizeStop={(e, direction, ref, delta, position) =>
              updateWindowState(name, {
                width: parseInt(ref.style.width, 10),
                height: parseInt(ref.style.height, 10),
                x: position.x,
                y: position.y,
              })
            }
            minWidth={200}
            minHeight={100}
            cancel=".window-content"
            disableDragging={state.maximized}
            enableResizing={!state.maximized}
            className="bg-white border border-gray-500 flex flex-col absolute"
            bounds="parent"
          >
            {/* Window Bar */}
            <div className="flex items-center justify-between bg-gray-200 p-1 cursor-move">
              <span className="pl-2">{name}</span>
              <div className="flex">
                <button
                  onClick={() => minimizeWindow(name)}
                  className="p-1 hover:bg-gray-300"
                >
                  <AiOutlineMinus />
                </button>
                <button
                  onClick={() => maximizeWindow(name)}
                  className="p-1 hover:bg-gray-300"
                >
                  <AiOutlineFullscreen />
                </button>
                <button
                  onClick={() => closeWindow(name)}
                  className="p-1 hover:bg-gray-300"
                >
                  <AiOutlineClose />
                </button>
              </div>
            </div>
            {/* Window Content */}
            <div className="flex-grow overflow-auto window-content">
              <Component />
            </div>
          </Rnd>
        );
      })}
    </div>
  );
};

export default DraggableWindows;

TASK: You will make it so that teh current window the user is interacting with is at the top shown abvove the other windows.