import { useState, useEffect, useCallback, lazy, Suspense } from 'react';
import ServerWidget from './components/ServerWidget';
import { DEFAULT_CATEGORIES } from './constants';
import { Category, Website, Config } from './types';
import Header from './components/layout/Header';
import EditButton from './components/layout/EditButton';
import ConfigurationButton from './components/layout/ConfigurationButton';
import CategoryGroup from './components/layout/CategoryGroup';
import Wallpaper from './components/Wallpaper';
import { ConfigurationService } from './components/services/ConfigurationService';
import { getAlignmentClass } from './components/utils/styleUtils';
import { getRandomWallpaperIndex } from './components/utils/wallpaperUtils';
import { PlusIcon } from './components/icons';

const ConfigurationModal = lazy(() => import('./components/ConfigurationModal'));
const WebsiteEditModal = lazy(() => import('./components/WebsiteEditModal'));
const CategoryEditModal = lazy(() => import('./components/CategoryEditModal'));

const App: React.FC = () => {
  const [categories, setCategories] = useState<Category[]>(() => {
    try {
      const storedCategories = localStorage.getItem('categories');
      if (storedCategories) {
        return JSON.parse(storedCategories);
      }
    } catch (error) {
      console.error('Error parsing categories from localStorage', error);
    }
    return DEFAULT_CATEGORIES;
  });
  const [isEditing, setIsEditing] = useState(false);
  const [isConfigModalOpen, setIsConfigModalOpen] = useState(false);
  const [editingWebsite, setEditingWebsite] = useState<Website | null>(null);
  const [addingWebsite, setAddingWebsite] = useState<Category | null>(null);
  const [editingCategory, setEditingCategory] = useState<Category | null>(null);
  const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false);
  const [config, setConfig] = useState<Config>(() => ConfigurationService.loadConfig());
  const [wallpaperVersion, setWallpaperVersion] = useState(0);

  useEffect(() => {
    ConfigurationService.saveConfig(config);
  }, [config]);

  useEffect(() => {
    try {
      localStorage.setItem('categories', JSON.stringify(categories));
    } catch (error) {
      console.error('Error saving categories to localStorage', error);
    }
  }, [categories]);

  const handleSaveConfig = useCallback((newConfig: Config) => {
    setConfig(newConfig);
    setIsConfigModalOpen(false);
  }, []);

  const handleWallpaperChange = useCallback((newConfig: Partial<Config>) => {
    setConfig(prev => ({ ...prev, ...newConfig }));
  }, []);

  const handleRandomWallpaper = useCallback(() => {
    const names = config.currentWallpapers;
    if (names.length === 0) return;
    try {
      const state = JSON.parse(localStorage.getItem('wallpaperState') || '{}');
      const current = typeof state.currentIndex === 'number' ? state.currentIndex : 0;
      const safeCurrent = current < 0 || current >= names.length ? 0 : current;
      const randomIndex = getRandomWallpaperIndex(names.length, safeCurrent);
      localStorage.setItem(
        'wallpaperState',
        JSON.stringify({
          lastWallpaperChange: new Date().toISOString(),
          currentIndex: randomIndex,
        }),
      );
    } catch (error) {
      console.error('Error randomizing wallpaper state', error);
    }
    setWallpaperVersion(v => v + 1);
  }, [config.currentWallpapers]);

  const handleSaveWebsite = useCallback((website: Partial<Website>) => {
    if (editingWebsite) {
      const idToUpdate = website.id ?? editingWebsite.id;
      const newCategories = categories.map(category => ({
        ...category,
        websites: category.websites.map(w =>
          w.id === idToUpdate ? { ...w, ...website, id: idToUpdate } : w
        ),
      }));
      setCategories(newCategories);
      setEditingWebsite(null);
    } else if (addingWebsite) {
      const newWebsite: Website = {
        id: Date.now().toString(),
        name: website.name || '',
        url: website.url || '',
        icon: website.icon || '',
        categoryId: addingWebsite.id,
      };
      const newCategories = categories.map(category =>
        category.id === addingWebsite.id
          ? { ...category, websites: [...category.websites, newWebsite] }
          : category
      );
      setCategories(newCategories);
      setAddingWebsite(null);
    }
  }, [editingWebsite, addingWebsite, categories]);

  const handleSaveCategory = useCallback((name: string) => {
    if (editingCategory) {
      const newCategories = categories.map(category =>
        category.id === editingCategory.id ? { ...category, name } : category
      );
      setCategories(newCategories);
    } else {
      const newCategory: Category = {
        id: Date.now().toString(),
        name,
        websites: [],
      };
      setCategories([...categories, newCategory]);
    }
    setEditingCategory(null);
    setIsCategoryModalOpen(false);
  }, [editingCategory, categories]);

  const handleDeleteWebsite = useCallback(() => {
    if (!editingWebsite) return;

    const newCategories = categories.map(category => ({
      ...category,
      websites: category.websites.filter(w => w.id !== editingWebsite.id),
    }));
    setCategories(newCategories);
    setEditingWebsite(null);
  }, [editingWebsite, categories]);

  const handleDeleteCategory = useCallback(() => {
    if (!editingCategory) return;

    const newCategories = categories.filter(c => c.id !== editingCategory.id);
    setCategories(newCategories);
    setEditingCategory(null);
    setIsCategoryModalOpen(false);
  }, [editingCategory, categories]);

  const handleMoveWebsite = useCallback((website: Website, direction: 'left' | 'right') => {
    const categoryIndex = categories.findIndex(cat => cat.websites.some(w => w.id === website.id));
    if (categoryIndex === -1) return;

    const category = categories[categoryIndex];
    const websiteIndex = category.websites.findIndex(w => w.id === website.id);
    if (websiteIndex === -1) return;

    const targetIndex = direction === 'left' ? websiteIndex - 1 : websiteIndex + 1;
    if (targetIndex < 0 || targetIndex >= category.websites.length) return;

    const newWebsites = [...category.websites];
    const [movedWebsite] = newWebsites.splice(websiteIndex, 1);
    newWebsites.splice(targetIndex, 0, movedWebsite);

    const newCategories = [...categories];
    newCategories[categoryIndex] = { ...category, websites: newWebsites };

    setCategories(newCategories);
  }, [categories]);

  return (
    <main
      className={`vision-shell min-h-screen w-full flex flex-col items-center ${getAlignmentClass(config.alignment)} px-4 py-8 sm:px-6 sm:py-10`}
    >
      <Wallpaper
        wallpaperNames={config.currentWallpapers}
        blur={config.wallpaperBlur}
        brightness={config.wallpaperBrightness}
        opacity={config.wallpaperOpacity}
        wallpaperFrequency={config.wallpaperFrequency}
        wallpaperVersion={wallpaperVersion}
      />
      <EditButton isEditing={isEditing} onClick={() => setIsEditing(!isEditing)} />
      <ConfigurationButton onClick={() => setIsConfigModalOpen(true)} />

      <Header config={config} />

      <div className="relative z-10 flex flex-col gap-7 sm:gap-8 w-full mt-12 sm:mt-14">
        {categories.map((category) => (
          <CategoryGroup
            key={category.id}
            category={category}
            isEditing={isEditing}
            setEditingCategory={setEditingCategory}
            setIsCategoryModalOpen={setIsCategoryModalOpen}
            setAddingWebsite={setAddingWebsite}
            setEditingWebsite={setEditingWebsite}
            handleMoveWebsite={handleMoveWebsite}
            horizontalAlignment={config.horizontalAlignment}
            tileSize={config.tileSize}
          />
        ))}
        {isEditing && (
          <div className="flex justify-center transition-all duration-200 ease-ios transform scale-100 opacity-100">
            <button
              onClick={() => {
                setEditingCategory(null);
                setIsCategoryModalOpen(true);
              }}
              className="liquid-surface liquid-control liquid-ghost-tile liquid-focus min-h-16 px-6 text-sm font-bold"
              aria-label="Add category"
            >
              <PlusIcon size={22} />
              Add category
            </button>
          </div>
        )}
      </div>

      {config.serverWidget.enabled && <ServerWidget config={config} />}

      {(editingWebsite || addingWebsite) && (
        <Suspense fallback={null}>
          <WebsiteEditModal
            website={editingWebsite || undefined}
            edit={!!editingWebsite}
            onClose={() => {
              setEditingWebsite(null);
              setAddingWebsite(null);
            }}
            onSave={handleSaveWebsite}
            onDelete={handleDeleteWebsite}
          />
        </Suspense>
      )}

      {isCategoryModalOpen && (
        <Suspense fallback={null}>
          <CategoryEditModal
            category={editingCategory || undefined}
            edit={!!editingCategory}
            onClose={() => {
              setEditingCategory(null);
              setIsCategoryModalOpen(false);
            }}
            onSave={handleSaveCategory}
            onDelete={handleDeleteCategory}
          />
        </Suspense>
      )}

      {isConfigModalOpen && (
        <Suspense fallback={null}>
          <ConfigurationModal
            currentConfig={config}
            onClose={() => setIsConfigModalOpen(false)}
            onSave={handleSaveConfig}
            onWallpaperChange={handleWallpaperChange}
            onRandomWallpaper={handleRandomWallpaper}
          />
        </Suspense>
      )}
    </main>
  );
}

export default App;
