import variables from 'config/variables';
import { memo, useRef, useState, useEffect, useCallback } from 'react';
import { toast } from 'react-toastify';
import {
  MdCancel,
  MdAddLink,
  MdAddPhotoAlternate,
  MdPersonalVideo,
  MdOutlineFileUpload,
  MdFolder,
  MdChevronLeft,
  MdChevronRight,
  MdImage,
} from 'react-icons/md';
import { BiSolidFilm } from 'react-icons/bi';

import EventBus from 'utils/eventbus';
import { compressAccurately, filetoDataURL } from 'image-conversion';
import videoCheck from '../api/videoCheck';
import {
  getAllBackgrounds,
  getAllBackgroundsWithMetadata,
  addBackground,
  deleteBackground,
  deleteMultipleBackgrounds,
  migrateFromLocalStorage,
  updateBackgroundMetadata,
} from 'utils/customBackgroundDB';
import {
  getImageDimensions,
  generateBlurHash,
  getDataUrlSize,
  getFileName,
  calculateStorageSize,
  calculateTotalStorageSize,
  formatBytes,
  extractVideoThumbnail,
} from 'utils/imageMetadata';
import { generateBlurHashDataUrl } from '../api/blurHash';

import { Checkbox, FileUpload, Dropdown } from 'components/Form/Settings';
import { Tooltip, Button } from 'components/Elements';
import Modal from 'react-modal';

import CustomURLModal from './CustomURLModal';
import FolderTaggingModal from './FolderTaggingModal';

const CustomSettings = memo(() => {
  const [customBackground, setCustomBackground] = useState([]);
  const [customURLModal, setCustomURLModal] = useState(false);
  const [folderTaggingModal, setFolderTaggingModal] = useState(false);
  const [pendingFiles, setPendingFiles] = useState([]);
  const [urlError, setUrlError] = useState('');
  const [isLoading, setIsLoading] = useState(true);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState({ current: 0, total: 0 });
  const [isDragging, setIsDragging] = useState(false);
  const [selectedImages, setSelectedImages] = useState(new Set());
  const [sortBy, setSortBy] = useState(localStorage.getItem('customImageSort') || 'date_desc');
  const [storageQuotaModal, setStorageQuotaModal] = useState(false);
  const [storageQuota, setStorageQuota] = useState({ usage: 0, quota: 0 });
  const customDnd = useRef(null);
  const dragCounter = useRef(0);

  // IndexedDB typically has 50MB+ quota, we'll check dynamically
  const FALLBACK_STORAGE_LIMIT = 50000000; // 50MB fallback if API unavailable

  // Fetch storage quota
  useEffect(() => {
    const fetchQuota = async () => {
      if (navigator.storage && navigator.storage.estimate) {
        try {
          const estimate = await navigator.storage.estimate();
          setStorageQuota({
            usage: estimate.usage || 0,
            quota: estimate.quota || FALLBACK_STORAGE_LIMIT,
          });
        } catch (error) {
          console.warn('Could not get storage estimate:', error);
          setStorageQuota({ usage: 0, quota: FALLBACK_STORAGE_LIMIT });
        }
      } else {
        setStorageQuota({ usage: 0, quota: FALLBACK_STORAGE_LIMIT });
      }
    };
    fetchQuota();
  }, [customBackground]);

  // Load backgrounds from IndexedDB on mount
  useEffect(() => {
    const loadBackgrounds = async () => {
      try {
        // Try migration first
        await migrateFromLocalStorage();

        // Load from IndexedDB
        const backgrounds = await getAllBackgroundsWithMetadata();
        setCustomBackground(backgrounds);

        // Backfill missing metadata for existing images
        backgrounds.forEach(async (bg) => {
          if (!bg.dimensions && bg.url && !videoCheck(bg.url)) {
            try {
              const dimensions = await getImageDimensions(bg.url);
              const blurHash = await generateBlurHash(bg.url);
              await updateBackgroundMetadata(bg.id, { dimensions, blurHash });
              // Reload backgrounds to show updated metadata
              const updatedBackgrounds = await getAllBackgroundsWithMetadata();
              setCustomBackground(updatedBackgrounds);
            } catch (error) {
              console.warn('Could not extract metadata for existing image:', error);
            }
          }
        });
      } catch (error) {
        console.error('Error loading backgrounds:', error);
        toast(variables.getMessage('toasts.error'));
      } finally {
        setIsLoading(false);
      }
    };

    loadBackgrounds();
  }, []);

  const handleCustomBackground = useCallback(
    async (file, dataUrl, metadata, skipRefresh = false) => {
      try {
        const backgroundData = {
          url: dataUrl,
          name: metadata.name,
          uploadDate: Date.now(),
          dimensions: metadata.dimensions,
          fileSize: metadata.fileSize,
          folder: metadata.folder || '',
          blurHash: metadata.blurHash,
          thumbnail: metadata.thumbnail || null,
        };

        await addBackground(backgroundData);

        // Reload from IndexedDB to get the latest state and update React state
        const backgrounds = await getAllBackgroundsWithMetadata();
        setCustomBackground(backgrounds);

        try {
          localStorage.setItem('customBackground', JSON.stringify(backgrounds.map((bg) => bg.url)));
        } catch (_quotaError) {
          console.warn('localStorage quota exceeded, storing count only');
          localStorage.setItem('customBackgroundCount', backgrounds.length.toString());
        }

        // Only emit refresh if not part of a batch upload
        if (!skipRefresh) {
          EventBus.emit('refresh', 'background');
        }
      } catch (error) {
        console.error('Error saving background:', error);
        toast(variables.getMessage('toasts.error'));
      }
    },
    [],
  );

  const processImageFile = async (file, folderName = '') => {
    // Calculate actual storage from existing backgrounds
    const storageSize = customBackground.reduce((total, bg) => {
      if (bg.url && bg.url.startsWith('data:')) {
        return total + getDataUrlSize(bg.url);
      }
      return total;
    }, 0);

    const availableQuota = storageQuota.quota || FALLBACK_STORAGE_LIMIT;

    // Request persistent storage if approaching limit (90%)
    if (storageSize / availableQuota > 0.9 && navigator.storage && navigator.storage.persist) {
      try {
        const isPersisted = await navigator.storage.persist();
        if (isPersisted) {
          console.log('Storage persistence granted');
        }
      } catch (error) {
        console.warn('Could not request storage persistence:', error);
      }
    }

    if (videoCheck(file.type)) {
      if (storageSize + file.size > availableQuota) {
        throw new Error('no_storage');
      }

      const reader = new FileReader();
      return new Promise((resolve, reject) => {
        reader.onloadend = async () => {
          try {
            // Extract thumbnail and dimensions from video
            const { thumbnail, dimensions } = await extractVideoThumbnail(reader.result);

            resolve({
              dataUrl: reader.result,
              metadata: {
                name: getFileName(file, customBackground.length),
                dimensions,
                fileSize: file.size,
                folder: folderName,
                blurHash: null,
                thumbnail,
              },
            });
          } catch (error) {
            console.warn('Could not extract video thumbnail:', error);
            // Fallback to no thumbnail if extraction fails
            resolve({
              dataUrl: reader.result,
              metadata: {
                name: getFileName(file, customBackground.length),
                dimensions: null,
                fileSize: file.size,
                folder: folderName,
                blurHash: null,
                thumbnail: null,
              },
            });
          }
        };
        reader.onerror = reject;
        reader.readAsDataURL(file);
      });
    } else {
      // Compress image
      const compressed = await compressAccurately(file, {
        size: 450,
        accuracy: 0.9,
      });

      const availableQuota = storageQuota.quota || FALLBACK_STORAGE_LIMIT;
      if (storageSize + compressed.size > availableQuota) {
        throw new Error('no_storage');
      }

      const dataUrl = await filetoDataURL(compressed);

      // Generate metadata in parallel
      const [dimensions, blurHash] = await Promise.all([
        getImageDimensions(dataUrl),
        generateBlurHash(dataUrl).catch(() => null), // Don't fail if blur hash fails
      ]);

      return {
        dataUrl,
        metadata: {
          name: getFileName(file, customBackground.length),
          dimensions,
          fileSize: getDataUrlSize(dataUrl),
          folder: folderName,
          blurHash,
        },
      };
    }
  };

  const handleBatchUpload = async (files, folderName = '') => {
    setIsUploading(true);
    setUploadProgress({ current: 0, total: files.length });

    const errors = [];

    for (let i = 0; i < files.length; i++) {
      try {
        const result = await processImageFile(files[i], folderName);
        // Skip refresh during batch upload to prevent background flashing
        await handleCustomBackground(files[i], result.dataUrl, result.metadata, true);
        setUploadProgress({ current: i + 1, total: files.length });
      } catch (error) {
        if (error.message === 'no_storage') {
          toast(variables.getMessage('toasts.no_storage'));
          break;
        }
        errors.push(files[i].name);
      }
    }

    if (errors.length > 0) {
      toast(variables.getMessage('toasts.error') + `: ${errors.join(', ')}`);
    }

    // Emit refresh once after all images are uploaded
    EventBus.emit('refresh', 'background');

    setIsUploading(false);
    setUploadProgress({ current: 0, total: 0 });
  };

  const handleFolderTagging = async (folderName) => {
    setFolderTaggingModal(false);
    await handleBatchUpload(pendingFiles, folderName);
    setPendingFiles([]);
  };

  const modifyCustomBackground = useCallback(async (type, index) => {
    try {
      if (type === 'add') {
        await addBackground('');
      } else {
        await deleteBackground(index);
      }

      // Reload from IndexedDB to get the latest state
      const backgrounds = await getAllBackgroundsWithMetadata();
      setCustomBackground(backgrounds);

      // Store in localStorage with quota handling
      try {
        localStorage.setItem('customBackground', JSON.stringify(backgrounds.map((bg) => bg.url)));
      } catch (_quotaError) {
        console.warn('localStorage quota exceeded, storing count only');
        localStorage.setItem('customBackgroundCount', backgrounds.length.toString());
      }

      EventBus.emit('refresh', 'background');
    } catch (error) {
      console.error('Error modifying background:', error);
      toast(variables.getMessage('toasts.error'));
    }
  }, []);

  const handleBatchDelete = async () => {
    if (selectedImages.size === 0) {
      return;
    }

    try {
      const indices = Array.from(selectedImages).sort((a, b) => b - a);
      await deleteMultipleBackgrounds(indices);

      // Reload from IndexedDB
      const backgrounds = await getAllBackgroundsWithMetadata();
      setCustomBackground(backgrounds);
      setSelectedImages(new Set());

      // Update localStorage
      try {
        localStorage.setItem('customBackground', JSON.stringify(backgrounds.map((bg) => bg.url)));
      } catch (_quotaError) {
        localStorage.setItem('customBackgroundCount', backgrounds.length.toString());
      }

      EventBus.emit('refresh', 'background');
      toast(variables.getMessage('toasts.deleted'));
    } catch (error) {
      console.error('Error batch deleting:', error);
      toast(variables.getMessage('toasts.error'));
    }
  };

  const toggleImageSelection = (index) => {
    const newSelection = new Set(selectedImages);
    if (newSelection.has(index)) {
      newSelection.delete(index);
    } else {
      newSelection.add(index);
    }
    setSelectedImages(newSelection);
  };

  const handleSort = (sortOption) => {
    setSortBy(sortOption);
    localStorage.setItem('customImageSort', sortOption);
  };

  const uploadCustomBackground = useCallback(() => {
    document.getElementById('bg-input').click();
  }, []);

  const addCustomURL = useCallback(
    async (e) => {
      // regex: https://ihateregex.io/expr/url/
      const urlRegex =
        /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._~#=]{1,256}\.[a-zA-Z0-9()]{1,63}\b([-a-zA-Z0-9()!@:%_.~#?&=]*)/;
      if (urlRegex.test(e) === false) {
        return setUrlError(variables.getMessage('widgets.quicklinks.url_error'));
      }

      setCustomURLModal(false);

      try {
        // Extract filename from URL
        const urlParts = e.split('/');
        const filename = urlParts[urlParts.length - 1].split('?')[0] || 'Remote Image';

        // Try to extract metadata from the remote image
        let dimensions = null;
        let blurHash = null;
        try {
          dimensions = await getImageDimensions(e);
          blurHash = await generateBlurHash(e);
        } catch (metadataError) {
          console.warn('Could not extract metadata from remote image:', metadataError);
        }

        const backgroundData = {
          url: e,
          name: filename,
          uploadDate: Date.now(),
          dimensions,
          fileSize: null, // Cannot determine file size for remote URLs without fetching
          folder: '',
          blurHash,
        };

        await addBackground(backgroundData);
        const backgrounds = await getAllBackgroundsWithMetadata();
        setCustomBackground(backgrounds);
      } catch (error) {
        console.error('Error adding URL:', error);
        toast(variables.getMessage('toasts.error'));
      }

      try {
        localStorage.setItem(
          'customBackground',
          JSON.stringify(updatedBackgrounds.map((bg) => bg.url)),
        );
      } catch (_quotaError) {
        localStorage.setItem('customBackgroundCount', updatedBackgrounds.length.toString());
      }

      EventBus.emit('refresh', 'background');
    },
    [customBackground.length],
  );

  const handleFileInputChange = async (files) => {
    if (files.length > 1) {
      // Multiple files - show tagging modal
      setPendingFiles(files);
      setFolderTaggingModal(true);
    } else {
      // Single file - upload directly
      await handleBatchUpload(files, '');
    }
  };

  // Sorted backgrounds
  const sortedBackgrounds = [...customBackground].sort((a, b) => {
    switch (sortBy) {
      case 'date_asc':
        return a.uploadDate - b.uploadDate;
      case 'date_desc':
        return b.uploadDate - a.uploadDate;
      case 'name_asc':
        return (a.name || '').localeCompare(b.name || '');
      case 'name_desc':
        return (b.name || '').localeCompare(a.name || '');
      case 'size_asc':
        return (a.fileSize || 0) - (b.fileSize || 0);
      case 'size_desc':
        return (b.fileSize || 0) - (a.fileSize || 0);
      default:
        return 0;
    }
  });

  // Calculate storage usage from actual background data
  const storageUsed = customBackground.reduce((total, bg) => {
    // Calculate size of the data URL
    if (bg.url && bg.url.startsWith('data:')) {
      return total + getDataUrlSize(bg.url);
    }
    return total;
  }, 0);
  const availableStorageLimit = storageQuota.quota || FALLBACK_STORAGE_LIMIT;
  const storagePercent = (storageUsed / availableStorageLimit) * 100;
  const totalStorageUsed = calculateTotalStorageSize();
  const TOTAL_STORAGE_LIMIT = 5242880; // 5MB total localStorage limit (browser default)

  useEffect(() => {
    const dnd = customDnd.current;
    if (!dnd) return;

    const handleDragOver = (e) => {
      e.preventDefault();
      e.stopPropagation();
    };

    const handleDragEnter = (e) => {
      e.preventDefault();
      e.stopPropagation();
      dragCounter.current++;
      if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
        setIsDragging(true);
      }
    };

    const handleDragLeave = (e) => {
      e.preventDefault();
      e.stopPropagation();
      dragCounter.current--;
      if (dragCounter.current === 0) {
        setIsDragging(false);
      }
    };

    const handleDrop = async (e) => {
      e.preventDefault();
      e.stopPropagation();
      setIsDragging(false);
      dragCounter.current = 0;

      const files = Array.from(e.dataTransfer.files);

      if (files.length === 0) {
        return;
      }

      if (files.length > 1) {
        // Multiple files - show tagging modal
        setPendingFiles(files);
        setFolderTaggingModal(true);
      } else {
        // Single file - upload directly
        await handleBatchUpload(files, '');
      }
    };

    dnd.ondragover = handleDragOver;
    dnd.ondragenter = handleDragEnter;
    dnd.ondragleave = handleDragLeave;
    dnd.ondrop = handleDrop;

    return () => {
      if (dnd) {
        dnd.ondragover = null;
        dnd.ondragenter = null;
        dnd.ondragleave = null;
        dnd.ondrop = null;
      }
    };
  }, [customBackground.length, handleBatchUpload]);

  const hasVideo = sortedBackgrounds.filter((bg) => bg && videoCheck(bg.url)).length > 0;

  if (isLoading) {
    return (
      <div className="photosEmpty">
        <div className="loaderHolder">
          <div id="loader"></div>
          <span className="subtitle">{variables.getMessage('modals.main.loading')}</span>
        </div>
      </div>
    );
  }

  if (isUploading) {
    return (
      <div className="photosEmpty">
        <div className="loaderHolder">
          <div id="loader"></div>
          <span className="subtitle">
            {variables.getMessage('modals.main.settings.sections.background.source.uploading', {
              current: uploadProgress.current,
              total: uploadProgress.total,
            })}
          </span>
          <span className="subtitle">
            {Math.round((uploadProgress.current / uploadProgress.total) * 100)}%
          </span>
        </div>
      </div>
    );
  }

  return (
    <>
      <div
        className={`dropzone ${isDragging ? 'dragging' : ''}`}
        ref={customDnd}
        style={
          isDragging
            ? {
                outline: '2px dashed #ff5c25',
                outlineOffset: '-2px',
                backgroundColor: 'rgba(255, 92, 37, 0.1)',
                transition: 'all 0.2s ease',
              }
            : {}
        }
      >
        <div className="imagesTopBar">
          <div className="imagesTopBarTitle">
            <MdAddPhotoAlternate />
            <div>
              <span className="title">
                {variables.getMessage(
                  'modals.main.settings.sections.background.source.custom_title',
                )}
              </span>
              <span className="subtitle">
                {variables.getMessage(
                  'modals.main.settings.sections.background.source.custom_description',
                )}
              </span>
            </div>
          </div>
          <div className="topbarbuttons">
            <Button
              type="settings"
              onClick={uploadCustomBackground}
              icon={<MdOutlineFileUpload />}
              label={variables.getMessage('modals.main.settings.sections.background.source.upload')}
            />
          </div>
        </div>

        <div className="imagesControlBar">
          <div className="controlBarLeft">
            <span className="image-count">
              {customBackground.length} {customBackground.length === 1 ? 'image' : 'images'}
              <span className="storage-info">
                {' '}
                · {formatBytes(storageUsed)} / {formatBytes(availableStorageLimit)}
                {storagePercent > 80 && navigator.storage && navigator.storage.persist && (
                  <Tooltip title="Request persistent storage to prevent browser from automatically clearing your images">
                    <button
                      className="request-storage-link"
                      onClick={async () => {
                        try {
                          const isPersisted = await navigator.storage.persist();
                          if (isPersisted) {
                            toast(
                              'Persistent storage granted - your images are protected from eviction',
                            );
                          } else {
                            toast(
                              'Persistent storage denied - images may be cleared if storage is low',
                            );
                          }
                        } catch (error) {
                          console.error('Storage request error:', error);
                          toast('Could not request persistent storage');
                        }
                      }}
                    >
                      Protect images
                    </button>
                  </Tooltip>
                )}
              </span>
            </span>
            {customBackground.length > 0 && <span className="selection-separator">·</span>}
            {selectedImages.size > 0 ? (
              <>
                <span className="selected-count">{selectedImages.size} selected</span>
                <button className="delete-link" onClick={handleBatchDelete}>
                  Delete
                </button>
                {selectedImages.size < customBackground.length && (
                  <button
                    className="select-all-link"
                    onClick={() => {
                      const allIndices = new Set(customBackground.map((_, i) => i));
                      setSelectedImages(allIndices);
                    }}
                  >
                    Select all
                  </button>
                )}
                {selectedImages.size === customBackground.length && (
                  <button className="select-all-link" onClick={() => setSelectedImages(new Set())}>
                    Deselect all
                  </button>
                )}
              </>
            ) : (
              customBackground.length > 0 && (
                <button
                  className="select-all-link"
                  onClick={() => {
                    const allIndices = new Set(customBackground.map((_, i) => i));
                    setSelectedImages(allIndices);
                  }}
                >
                  Select all
                </button>
              )
            )}
          </div>
          <div className="controlBarRight">
            <Dropdown
              name="customImageSort"
              category="customImageSort"
              onChange={handleSort}
              items={[
                {
                  value: 'date_desc',
                  text: variables.getMessage(
                    'modals.main.settings.sections.background.source.sort.date_newest',
                  ),
                },
                {
                  value: 'date_asc',
                  text: variables.getMessage(
                    'modals.main.settings.sections.background.source.sort.date_oldest',
                  ),
                },
                {
                  value: 'name_asc',
                  text: variables.getMessage(
                    'modals.main.settings.sections.background.source.sort.name_asc',
                  ),
                },
                {
                  value: 'name_desc',
                  text: variables.getMessage(
                    'modals.main.settings.sections.background.source.sort.name_desc',
                  ),
                },
                {
                  value: 'size_asc',
                  text: variables.getMessage(
                    'modals.main.settings.sections.background.source.sort.size_small',
                  ),
                },
                {
                  value: 'size_desc',
                  text: variables.getMessage(
                    'modals.main.settings.sections.background.source.sort.size_large',
                  ),
                },
              ]}
            />
          </div>
        </div>

        <div className="dropzone-content">
          {sortedBackgrounds.length > 0 ? (
            <div className={`images-grid ${selectedImages.size > 0 ? 'selection-mode' : ''}`}>
              {sortedBackgrounds.map((bg, index) => {
                const originalIndex = customBackground.findIndex((item) => item === bg);
                const isVideo = bg && videoCheck(bg.url);

                return (
                  <div
                    key={originalIndex}
                    className="image-card"
                    onClick={(e) => {
                      // Only select if clicking the card itself, not navigation buttons
                      if (!e.target.closest('.image-nav-buttons')) {
                        toggleImageSelection(originalIndex);
                      }
                    }}
                  >
                    <div className="image-checkbox">
                      <input
                        type="checkbox"
                        checked={selectedImages.has(originalIndex)}
                        onChange={() => toggleImageSelection(originalIndex)}
                      />
                    </div>
                    <div className="image-preview">
                      {bg.blurHash &&
                        !isVideo &&
                        (() => {
                          const blurHashDataUrl = generateBlurHashDataUrl(bg.blurHash, 32, 32);
                          return blurHashDataUrl ? (
                            <div
                              className="blur-placeholder"
                              style={{
                                backgroundImage: `url(${blurHashDataUrl})`,
                                filter: 'blur(20px)',
                                position: 'absolute',
                                top: 0,
                                left: 0,
                                right: 0,
                                bottom: 0,
                                zIndex: 0,
                              }}
                            />
                          ) : null;
                        })()}
                      {isVideo ? (
                        bg.thumbnail ? (
                          <>
                            <img
                              alt={bg.name || 'Custom video'}
                              src={bg.thumbnail}
                              loading="lazy"
                              style={{ position: 'relative', zIndex: 1 }}
                            />
                            <div
                              className="video-overlay-icon"
                              style={{
                                position: 'absolute',
                                top: '8px',
                                right: '8px',
                                zIndex: 2,
                                background: 'rgba(0, 0, 0, 0.6)',
                                borderRadius: '4px',
                                padding: '4px',
                                display: 'flex',
                                alignItems: 'center',
                                justifyContent: 'center',
                              }}
                            >
                              <BiSolidFilm style={{ fontSize: '20px', color: 'white' }} />
                            </div>
                          </>
                        ) : (
                          <div className="video-icon-wrapper">
                            <MdPersonalVideo className="customvideoicon" />
                          </div>
                        )
                      ) : (
                        <>
                          <img
                            alt={bg.name || 'Custom background'}
                            src={bg.url}
                            loading="lazy"
                            style={{ position: 'relative', zIndex: 1 }}
                          />
                          <div
                            className="photo-overlay-icon"
                            style={{
                              position: 'absolute',
                              top: '8px',
                              right: '8px',
                              zIndex: 2,
                              background: 'rgba(0, 0, 0, 0.6)',
                              borderRadius: '4px',
                              padding: '4px',
                              display: 'flex',
                              alignItems: 'center',
                              justifyContent: 'center',
                            }}
                          >
                            <MdImage style={{ fontSize: '20px', color: 'white' }} />
                          </div>
                        </>
                      )}
                      <div className="image-nav-buttons">
                        <button
                          className="nav-button nav-prev"
                          onClick={() => {
                            if (index > 0) {
                              const prevBg = sortedBackgrounds[index - 1];
                              EventBus.emit('refresh', 'background', prevBg.url);
                            }
                          }}
                          disabled={index === 0}
                        >
                          <MdChevronLeft />
                        </button>
                        <button
                          className="nav-button nav-next"
                          onClick={() => {
                            if (index < sortedBackgrounds.length - 1) {
                              const nextBg = sortedBackgrounds[index + 1];
                              EventBus.emit('refresh', 'background', nextBg.url);
                            }
                          }}
                          disabled={index === sortedBackgrounds.length - 1}
                        >
                          <MdChevronRight />
                        </button>
                      </div>
                    </div>
                    <div className="image-metadata">
                      <span className="image-name" title={bg.name}>
                        {bg.name || 'Unnamed'}
                      </span>
                      <div className="image-details">
                        {bg.dimensions && (
                          <span className="detail">
                            {bg.dimensions.width} × {bg.dimensions.height}
                          </span>
                        )}
                        {bg.fileSize && <span className="detail">{formatBytes(bg.fileSize)}</span>}
                        {bg.folder && <span className="detail folder-tag">{bg.folder}</span>}
                      </div>
                    </div>
                    <Tooltip
                      title={variables.getMessage(
                        'modals.main.settings.sections.background.source.remove',
                      )}
                    >
                      <button
                        className="delete-button"
                        onClick={() => modifyCustomBackground('remove', originalIndex)}
                      >
                        <MdCancel />
                      </button>
                    </Tooltip>
                  </div>
                );
              })}
            </div>
          ) : (
            <div className="photosEmpty">
              <div className="emptyNewMessage">
                <MdAddPhotoAlternate />
                <span className="title">
                  {variables.getMessage(
                    'modals.main.settings.sections.background.source.drop_to_upload',
                  )}
                </span>
                <span className="subtitle">
                  {variables.getMessage('modals.main.settings.sections.background.source.formats', {
                    list: 'jpeg, png, webp, webm, gif, mp4, webm, ogg',
                  })}
                </span>
                <Button
                  type="settings"
                  onClick={uploadCustomBackground}
                  icon={<MdFolder />}
                  label={variables.getMessage(
                    'modals.main.settings.sections.background.source.select',
                  )}
                />
              </div>
            </div>
          )}
        </div>
      </div>

      <FileUpload
        id="bg-input"
        accept="image/jpeg, image/png, image/webp, image/webm, image/gif, video/mp4, video/webm, video/ogg"
        multiple
        loadFunction={async (files) => {
          await handleFileInputChange(files);
        }}
      />

      {hasVideo && (
        <>
          <Checkbox
            name="backgroundVideoLoop"
            text={variables.getMessage(
              'modals.main.settings.sections.background.source.loop_video',
            )}
          />
          <Checkbox
            name="backgroundVideoMute"
            text={variables.getMessage(
              'modals.main.settings.sections.background.source.mute_video',
            )}
          />
        </>
      )}

      <Modal
        closeTimeoutMS={100}
        onRequestClose={() => setCustomURLModal(false)}
        isOpen={customURLModal}
        className="Modal resetmodal mainModal"
        overlayClassName="Overlay resetoverlay"
        ariaHideApp={false}
      >
        <CustomURLModal
          modalClose={addCustomURL}
          urlError={urlError}
          modalCloseOnly={() => setCustomURLModal(false)}
        />
      </Modal>

      <Modal
        closeTimeoutMS={100}
        onRequestClose={() => {
          setFolderTaggingModal(false);
          setPendingFiles([]);
        }}
        isOpen={folderTaggingModal}
        className="Modal resetmodal mainModal"
        overlayClassName="Overlay resetoverlay"
        ariaHideApp={false}
      >
        <FolderTaggingModal
          files={pendingFiles}
          onConfirm={handleFolderTagging}
          onCancel={() => {
            setFolderTaggingModal(false);
            setPendingFiles([]);
          }}
        />
      </Modal>

      <Modal
        closeTimeoutMS={100}
        onRequestClose={() => setStorageQuotaModal(false)}
        isOpen={storageQuotaModal}
        className="Modal resetmodal mainModal"
        overlayClassName="Overlay resetoverlay"
        ariaHideApp={false}
      >
        <div className="smallModal">
          <div className="shareHeader">
            <span className="title">
              {variables.getMessage('modals.main.settings.sections.background.source.storage_info')}
            </span>
            <button className="closeModal" onClick={() => setStorageQuotaModal(false)}>
              <MdCancel />
            </button>
          </div>
          <div style={{ padding: '20px' }}>
            <p className="subtitle">
              {variables.getMessage(
                'modals.main.settings.sections.background.source.storage_description',
              )}
            </p>
            <div style={{ marginTop: '20px' }}>
              <p className="subtitle" style={{ fontWeight: '600', marginBottom: '8px' }}>
                Custom Backgrounds
              </p>
              <p className="subtitle">
                {formatBytes(storageUsed)} / {formatBytes(availableStorageLimit)} (
                {Math.round(storagePercent)}%)
              </p>
            </div>
            <div style={{ marginTop: '15px' }}>
              <p className="subtitle" style={{ fontWeight: '600', marginBottom: '8px' }}>
                Total localStorage Usage
              </p>
              <p className="subtitle">
                {formatBytes(totalStorageUsed)} / {formatBytes(TOTAL_STORAGE_LIMIT)} (
                {Math.round((totalStorageUsed / TOTAL_STORAGE_LIMIT) * 100)}%)
              </p>
              <p className="subtitle" style={{ marginTop: '8px', fontSize: '12px', opacity: 0.7 }}>
                Includes all Mue settings and custom images
              </p>
            </div>
          </div>
          <div className="resetFooter">
            <Button
              type="settings"
              onClick={() => setStorageQuotaModal(false)}
              label={variables.getMessage('modals.main.settings.buttons.close')}
            />
          </div>
        </div>
      </Modal>
    </>
  );
});

CustomSettings.displayName = 'CustomSettings';

export default CustomSettings;
