/**
 * Hook for managing widget layouts
 */

import { useCallback, useState, useEffect } from "react";
import type { WidgetPlacement, LayoutConfig } from "@mosaic/shared";

const STORAGE_KEY = "mosaic-layout";
const DEFAULT_LAYOUT_NAME = "default";

/**
 * Local storage key for user's workspace preference
 */
const WORKSPACE_KEY = "mosaic-workspace-id";

interface UseLayoutReturn {
  layouts: Record<string, LayoutConfig>;
  currentLayout: LayoutConfig | undefined;
  currentLayoutId: string;
  isLoading: boolean;
  updateLayout: (layoutItems: WidgetPlacement[]) => void;
  addWidget: (widget: WidgetPlacement) => void;
  removeWidget: (widgetId: string) => void;
  updateWidget: (widgetId: string, updates: Partial<WidgetPlacement>) => void;
  createLayout: (name: string) => string;
  deleteLayout: (layoutId: string) => void;
  renameLayout: (layoutId: string, name: string) => void;
  switchLayout: (layoutId: string) => void;
  resetLayout: () => void;
}

/**
 * Hook to manage widget layout state
 */
export function useLayout(): UseLayoutReturn {
  const [layouts, setLayouts] = useState<Record<string, LayoutConfig>>({});
  const [currentLayoutId, setCurrentLayoutId] = useState<string>(DEFAULT_LAYOUT_NAME);
  const [isLoading, setIsLoading] = useState(true);

  // Load layouts from localStorage on mount
  useEffect(() => {
    try {
      const stored = localStorage.getItem(STORAGE_KEY);
      if (stored) {
        const parsed = JSON.parse(stored) as Record<string, LayoutConfig>;
        setLayouts(parsed);
      }

      // Load current layout ID preference
      const storedLayoutId = localStorage.getItem(`${STORAGE_KEY}-current`);
      if (storedLayoutId) {
        setCurrentLayoutId(storedLayoutId);
      }
    } catch (error) {
      console.error("Failed to load layouts from localStorage:", error);
    } finally {
      setIsLoading(false);
    }
  }, []);

  // Save layouts to localStorage whenever they change
  useEffect(() => {
    if (!isLoading) {
      try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(layouts));
        localStorage.setItem(`${STORAGE_KEY}-current`, currentLayoutId);
      } catch (error) {
        console.error("Failed to save layouts to localStorage:", error);
      }
    }
  }, [layouts, currentLayoutId, isLoading]);

  const currentLayout = layouts[currentLayoutId];

  const updateLayout = useCallback(
    (layoutItems: WidgetPlacement[]) => {
      setLayouts((prev) => ({
        ...prev,
        [currentLayoutId]: {
          id: currentLayoutId,
          name: prev[currentLayoutId]?.name ?? "My Layout",
          layout: layoutItems,
        },
      }));
    },
    [currentLayoutId]
  );

  const addWidget = useCallback(
    (widget: WidgetPlacement) => {
      setLayouts((prev) => {
        const currentLayoutData = prev[currentLayoutId];
        if (!currentLayoutData) {
          return prev;
        }

        return {
          ...prev,
          [currentLayoutId]: {
            ...currentLayoutData,
            layout: [...currentLayoutData.layout, widget],
          },
        };
      });
    },
    [currentLayoutId]
  );

  const removeWidget = useCallback(
    (widgetId: string) => {
      setLayouts((prev) => {
        const currentLayoutData = prev[currentLayoutId];
        if (!currentLayoutData) {
          return prev;
        }

        return {
          ...prev,
          [currentLayoutId]: {
            ...currentLayoutData,
            layout: currentLayoutData.layout.filter((w) => w.i !== widgetId),
          },
        };
      });
    },
    [currentLayoutId]
  );

  const updateWidget = useCallback(
    (widgetId: string, updates: Partial<WidgetPlacement>) => {
      setLayouts((prev) => {
        const currentLayoutData = prev[currentLayoutId];
        if (!currentLayoutData) {
          return prev;
        }

        return {
          ...prev,
          [currentLayoutId]: {
            ...currentLayoutData,
            layout: currentLayoutData.layout.map((w) =>
              w.i === widgetId ? { ...w, ...updates } : w
            ),
          },
        };
      });
    },
    [currentLayoutId]
  );

  const createLayout = useCallback((name: string) => {
    const id = `layout-${String(Date.now())}`;
    setLayouts((prev) => ({
      ...prev,
      [id]: {
        id,
        name,
        layout: [],
      },
    }));
    setCurrentLayoutId(id);
    return id;
  }, []);

  const deleteLayout = useCallback(
    (layoutId: string) => {
      setLayouts((prev) => {
        const { [layoutId]: _deleted, ...rest } = prev;
        // If we deleted the current layout, switch to default
        if (layoutId === currentLayoutId) {
          const remainingIds = Object.keys(rest);
          setCurrentLayoutId(remainingIds[0] ?? DEFAULT_LAYOUT_NAME);
        }
        return rest;
      });
    },
    [currentLayoutId]
  );

  const renameLayout = useCallback((layoutId: string, name: string) => {
    setLayouts((prev) => {
      const existing = prev[layoutId];
      if (!existing) return prev;
      return {
        ...prev,
        [layoutId]: {
          ...existing,
          name,
        },
      };
    });
  }, []);

  const resetLayout = useCallback(() => {
    setLayouts({
      [DEFAULT_LAYOUT_NAME]: {
        id: DEFAULT_LAYOUT_NAME,
        name: "Default Layout",
        layout: [],
      },
    });
    setCurrentLayoutId(DEFAULT_LAYOUT_NAME);
  }, []);

  return {
    layouts,
    currentLayout,
    currentLayoutId,
    isLoading,
    updateLayout,
    addWidget,
    removeWidget,
    updateWidget,
    createLayout,
    deleteLayout,
    renameLayout,
    switchLayout: setCurrentLayoutId,
    resetLayout,
  };
}

/**
 * Hook to get the current workspace ID
 */
export function useWorkspaceId(): string | null {
  const [workspaceId, setWorkspaceId] = useState<string | null>(null);

  useEffect(() => {
    try {
      const stored = localStorage.getItem(WORKSPACE_KEY);
      if (stored) {
        setWorkspaceId(stored);
      }
    } catch (error) {
      console.error("Failed to load workspace ID from localStorage:", error);
    }
  }, []);

  return workspaceId;
}
