'use client';

import React, { useState, useEffect } from 'react';
import Button from '../ui/Button';
import { databaseApi, configApi, searchAdminApi } from '../../lib/api';

interface SystemSettingsProps {
  // No props needed - this component manages its own state
}

export default function SystemSettings({}: SystemSettingsProps) {
  const [searchEngineStatus, setSearchEngineStatus] = useState<{
    currentEngine: string;
    solrAvailable: boolean;
    loading: boolean;
    message: string;
    success?: boolean;
  }>({
    currentEngine: 'solr',
    solrAvailable: false,
    loading: false,
    message: ''
  });

  const [solrStatus, setSolrStatus] = useState<{
    reindex: { loading: boolean; message: string; success?: boolean };
    recreate: { loading: boolean; message: string; success?: boolean };
    migrate: { loading: boolean; message: string; success?: boolean };
  }>({
    reindex: { loading: false, message: '' },
    recreate: { loading: false, message: '' },
    migrate: { loading: false, message: '' }
  });

  const [databaseStatus, setDatabaseStatus] = useState<{
    completeBackup: {
      loading: boolean;
      message: string;
      success?: boolean;
      jobId?: string;
      progress?: number;
    };
    completeClear: { loading: boolean; message: string; success?: boolean };
  }>({
    completeBackup: { loading: false, message: '', progress: 0 },
    completeClear: { loading: false, message: '' }
  });

  const [backupList, setBackupList] = useState<{
    loading: boolean;
    backups: Array<{ filename: string; sizeBytes: number; createdAt: string; origin: 'MANUAL' | 'AUTO' | 'UNKNOWN' }>;
    error?: string;
  }>({ loading: false, backups: [] });

  const [restoreStatus, setRestoreStatus] = useState<{
    loading: boolean;
    filename?: string;
    message: string;
    success?: boolean;
  }>({ loading: false, message: '' });
  const [cleanupStatus, setCleanupStatus] = useState<{
    preview: { loading: boolean; message: string; success?: boolean; data?: any };
    execute: { loading: boolean; message: string; success?: boolean };
  }>({
    preview: { loading: false, message: '' },
    execute: { loading: false, message: '' }
  });

  const [migrationStatus, setMigrationStatus] = useState<{
    preview: { loading: boolean; message: string; success?: boolean; data?: any };
    execute: { loading: boolean; message: string; success?: boolean };
  }>({
    preview: { loading: false, message: '' },
    execute: { loading: false, message: '' }
  });

  const [hoveredImage, setHoveredImage] = useState<{ src: string; alt: string } | null>(null);
  const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 });

  const loadBackups = async () => {
    setBackupList(prev => ({ ...prev, loading: true, error: undefined }));
    try {
      const result = await databaseApi.listBackupFiles();
      setBackupList({ loading: false, backups: result.backups });
    } catch (error: any) {
      setBackupList({ loading: false, backups: [], error: error.message || 'Failed to load backups' });
    }
  };

  useEffect(() => {
    loadBackups();
  }, []);

  const handleImageHover = (filePath: string, fileName: string, event: React.MouseEvent) => {
    // Convert backend file path to frontend image URL
    const imageUrl = filePath.replace(/^.*\/images\//, '/images/');
    setHoveredImage({ src: imageUrl, alt: fileName });
    setMousePosition({ x: event.clientX, y: event.clientY });
  };

  const handleImageLeave = () => {
    setHoveredImage(null);
  };

  const isImageFile = (fileName: string): boolean => {
    const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg'];
    return imageExtensions.some(ext => fileName.toLowerCase().endsWith(ext));
  };



  const handleCompleteBackup = async () => {
    setDatabaseStatus(prev => ({
      ...prev,
      completeBackup: { loading: true, message: 'Starting backup...', success: undefined, progress: 0 }
    }));

    try {
      const startResponse = await databaseApi.backupComplete();
      const jobId = startResponse.jobId;

      setDatabaseStatus(prev => ({
        ...prev,
        completeBackup: { ...prev.completeBackup, jobId, message: 'Backup in progress...' }
      }));

      const pollInterval = setInterval(async () => {
        try {
          const status = await databaseApi.getBackupStatus(jobId);

          if (status.status === 'COMPLETED') {
            clearInterval(pollInterval);
            setDatabaseStatus(prev => ({
              ...prev,
              completeBackup: { loading: false, message: 'Backup created successfully.', success: true, jobId, progress: 100 }
            }));
            loadBackups();
            setTimeout(() => {
              setDatabaseStatus(prev => ({ ...prev, completeBackup: { ...prev.completeBackup, message: '' } }));
            }, 8000);
          } else if (status.status === 'FAILED') {
            clearInterval(pollInterval);
            setDatabaseStatus(prev => ({
              ...prev,
              completeBackup: { loading: false, message: `Backup failed: ${status.errorMessage}`, success: false, progress: 0 }
            }));
          } else {
            setDatabaseStatus(prev => ({
              ...prev,
              completeBackup: { ...prev.completeBackup, progress: status.progress, message: `Creating backup... ${status.progress}%` }
            }));
          }
        } catch (pollError: any) {
          clearInterval(pollInterval);
          setDatabaseStatus(prev => ({
            ...prev,
            completeBackup: { loading: false, message: `Failed to check backup status: ${pollError.message}`, success: false, progress: 0 }
          }));
        }
      }, 2000);

    } catch (error: any) {
      setDatabaseStatus(prev => ({
        ...prev,
        completeBackup: { loading: false, message: error.message || 'Failed to start backup', success: false, progress: 0 }
      }));
    }
  };

  const handleRestoreFromFile = async (filename: string) => {
    const confirmed = window.confirm(
      `Are you sure you want to restore "${filename}"? This will PERMANENTLY DELETE all current data AND files (cover images, avatars) and replace them with the backup data. This action cannot be undone!`
    );
    if (!confirmed) return;

    setRestoreStatus({ loading: true, filename, message: 'Restoring backup...' });

    try {
      const result = await databaseApi.restoreFromFile(filename);
      setRestoreStatus({ loading: false, filename, message: result.message, success: result.success });
    } catch (error: any) {
      setRestoreStatus({ loading: false, filename, message: error.message || 'Restore failed', success: false });
    }

    setTimeout(() => setRestoreStatus({ loading: false, message: '' }), 10000);
  };

  const handleDownloadBackupFile = (filename: string) => {
    const url = databaseApi.downloadBackupFile(filename);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  const handleDeleteBackupFile = async (filename: string) => {
    const confirmed = window.confirm(`Delete backup "${filename}"? This cannot be undone.`);
    if (!confirmed) return;

    try {
      await databaseApi.deleteBackupFile(filename);
      loadBackups();
    } catch (error: any) {
      alert(`Failed to delete backup: ${error.message}`);
    }
  };

  const handleCompleteClear = async () => {
    const confirmed = window.confirm(
      'Are you ABSOLUTELY SURE you want to clear the entire database AND all files? This will PERMANENTLY DELETE ALL stories, authors, series, tags, collections, AND all uploaded images (covers, avatars). This action cannot be undone!'
    );

    if (!confirmed) return;

    const doubleConfirmed = window.confirm(
      'This is your final warning! Clicking OK will DELETE EVERYTHING in your StoryCove database AND all uploaded files. Are you completely certain you want to proceed?'
    );

    if (!doubleConfirmed) return;

    setDatabaseStatus(prev => ({
      ...prev,
      completeClear: { loading: true, message: 'Clearing database and files...', success: undefined }
    }));

    try {
      const result = await databaseApi.clearComplete();
      setDatabaseStatus(prev => ({
        ...prev,
        completeClear: {
          loading: false,
          message: result.success
            ? `Database and files cleared successfully. Deleted ${result.deletedRecords} records.`
            : result.message,
          success: result.success
        }
      }));
    } catch (error: any) {
      setDatabaseStatus(prev => ({
        ...prev,
        completeClear: { loading: false, message: error.message || 'Clear operation failed', success: false }
      }));
    }

    // Clear message after 10 seconds for clear (longer because it's important)
    setTimeout(() => {
      setDatabaseStatus(prev => ({
        ...prev,
        completeClear: { loading: false, message: '', success: undefined }
      }));
    }, 10000);
  };

  const handleImageCleanupPreview = async () => {
    setCleanupStatus(prev => ({
      ...prev,
      preview: { loading: true, message: 'Scanning for orphaned images...', success: undefined }
    }));

    try {
      const result = await configApi.previewImageCleanup();

      if (result.success) {
        setCleanupStatus(prev => ({
          ...prev,
          preview: {
            loading: false,
            message: `Found ${result.orphanedCount} orphaned images (${result.formattedSize}) and ${result.foldersToDelete} empty folders. Referenced images: ${result.referencedImagesCount}`,
            success: true,
            data: result
          }
        }));
      } else {
        setCleanupStatus(prev => ({
          ...prev,
          preview: {
            loading: false,
            message: result.error || 'Preview failed',
            success: false
          }
        }));
      }
    } catch (error: any) {
      setCleanupStatus(prev => ({
        ...prev,
        preview: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));
    }

    // Note: Preview message no longer auto-clears to allow users to review file details
  };

  const handleImageCleanupExecute = async () => {
    if (!cleanupStatus.preview.data || cleanupStatus.preview.data.orphanedCount === 0) {
      setCleanupStatus(prev => ({
        ...prev,
        execute: {
          loading: false,
          message: 'Please run preview first to see what will be deleted',
          success: false
        }
      }));
      return;
    }

    const confirmed = window.confirm(
      `Are you sure you want to delete ${cleanupStatus.preview.data.orphanedCount} orphaned images (${cleanupStatus.preview.data.formattedSize})? This action cannot be undone!`
    );

    if (!confirmed) return;

    setCleanupStatus(prev => ({
      ...prev,
      execute: { loading: true, message: 'Deleting orphaned images...', success: undefined }
    }));

    try {
      const result = await configApi.executeImageCleanup();

      if (result.success) {
        setCleanupStatus(prev => ({
          ...prev,
          execute: {
            loading: false,
            message: `Successfully deleted ${result.deletedCount} orphaned images (${result.formattedSize}) and ${result.foldersDeleted} empty folders`,
            success: true
          },
          preview: { loading: false, message: '', success: undefined, data: undefined } // Clear preview after successful cleanup
        }));
      } else {
        setCleanupStatus(prev => ({
          ...prev,
          execute: {
            loading: false,
            message: result.error || 'Cleanup failed',
            success: false
          }
        }));
      }
    } catch (error: any) {
      setCleanupStatus(prev => ({
        ...prev,
        execute: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));
    }

    // Clear message after 10 seconds
    setTimeout(() => {
      setCleanupStatus(prev => ({
        ...prev,
        execute: { loading: false, message: '', success: undefined }
      }));
    }, 10000);
  };

  const handleEpubMigrationPreview = async () => {
    setMigrationStatus(prev => ({
      ...prev,
      preview: { loading: true, message: 'Scanning for misplaced EPUB images...', success: undefined }
    }));

    try {
      const result = await configApi.previewEpubImageMigration();

      if (result.success) {
        const matchedCount = result.movedFiles.filter(f => f.action !== 'unmatched').length;
        setMigrationStatus(prev => ({
          ...prev,
          preview: {
            loading: false,
            message: `Found ${matchedCount} image(s) to move into story subfolders, ${result.unmatchedCount} unmatched (no story reference found).`,
            success: true,
            data: result
          }
        }));
      } else {
        setMigrationStatus(prev => ({
          ...prev,
          preview: {
            loading: false,
            message: result.error || 'Preview failed',
            success: false
          }
        }));
      }
    } catch (error: any) {
      setMigrationStatus(prev => ({
        ...prev,
        preview: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));
    }
  };

  const handleEpubMigrationExecute = async () => {
    const matchedCount = migrationStatus.preview.data?.movedFiles?.filter((f: any) => f.action !== 'unmatched').length ?? 0;

    if (!migrationStatus.preview.data || matchedCount === 0) {
      setMigrationStatus(prev => ({
        ...prev,
        execute: {
          loading: false,
          message: 'Please run preview first, or there are no images to migrate.',
          success: false
        }
      }));
      return;
    }

    const confirmed = window.confirm(
      `Move ${matchedCount} EPUB image(s) into their story subfolders? Story content URLs will be updated automatically.`
    );
    if (!confirmed) return;

    setMigrationStatus(prev => ({
      ...prev,
      execute: { loading: true, message: 'Migrating EPUB images...', success: undefined }
    }));

    try {
      const result = await configApi.executeEpubImageMigration();

      if (result.success) {
        setMigrationStatus(prev => ({
          ...prev,
          execute: {
            loading: false,
            message: `Successfully moved ${result.movedCount} image(s). ${result.unmatchedCount} unmatched file(s) left in place.${result.hasErrors ? ` Errors: ${result.errors.length}` : ''}`,
            success: true
          },
          preview: { loading: false, message: '', success: undefined, data: undefined }
        }));
      } else {
        setMigrationStatus(prev => ({
          ...prev,
          execute: {
            loading: false,
            message: result.error || 'Migration failed',
            success: false
          }
        }));
      }
    } catch (error: any) {
      setMigrationStatus(prev => ({
        ...prev,
        execute: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));
    }

    setTimeout(() => {
      setMigrationStatus(prev => ({
        ...prev,
        execute: { loading: false, message: '', success: undefined }
      }));
    }, 10000);
  };

  // Search Engine Management Functions
  const loadSearchEngineStatus = async () => {
    try {
      const status = await searchAdminApi.getStatus();
      setSearchEngineStatus(prev => ({
        ...prev,
        currentEngine: status.primaryEngine,
        solrAvailable: status.solrAvailable,
      }));
    } catch (error: any) {
      console.error('Failed to load search engine status:', error);
    }
  };



  const handleSolrReindex = async () => {
    setSolrStatus(prev => ({
      ...prev,
      reindex: { loading: true, message: 'Reindexing Solr...', success: undefined }
    }));

    try {
      const result = await searchAdminApi.reindexSolr();

      setSolrStatus(prev => ({
        ...prev,
        reindex: {
          loading: false,
          message: result.success ? result.message : (result.error || 'Reindex failed'),
          success: result.success
        }
      }));

      setTimeout(() => {
        setSolrStatus(prev => ({
          ...prev,
          reindex: { loading: false, message: '', success: undefined }
        }));
      }, 8000);
    } catch (error: any) {
      setSolrStatus(prev => ({
        ...prev,
        reindex: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));

      setTimeout(() => {
        setSolrStatus(prev => ({
          ...prev,
          reindex: { loading: false, message: '', success: undefined }
        }));
      }, 8000);
    }
  };

  const handleSolrRecreate = async () => {
    setSolrStatus(prev => ({
      ...prev,
      recreate: { loading: true, message: 'Recreating Solr indices...', success: undefined }
    }));

    try {
      const result = await searchAdminApi.recreateSolrIndices();

      setSolrStatus(prev => ({
        ...prev,
        recreate: {
          loading: false,
          message: result.success ? result.message : (result.error || 'Recreation failed'),
          success: result.success
        }
      }));

      setTimeout(() => {
        setSolrStatus(prev => ({
          ...prev,
          recreate: { loading: false, message: '', success: undefined }
        }));
      }, 8000);
    } catch (error: any) {
      setSolrStatus(prev => ({
        ...prev,
        recreate: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));

      setTimeout(() => {
        setSolrStatus(prev => ({
          ...prev,
          recreate: { loading: false, message: '', success: undefined }
        }));
      }, 8000);
    }
  };

  const handleLibraryMigration = async () => {
    const confirmed = window.confirm(
      'This will migrate Solr to support library separation. It will clear existing search data and reindex with library context. Continue?'
    );

    if (!confirmed) return;

    setSolrStatus(prev => ({
      ...prev,
      migrate: { loading: true, message: 'Migrating to library-aware schema...', success: undefined }
    }));

    try {
      const result = await searchAdminApi.migrateLibrarySchema();

      setSolrStatus(prev => ({
        ...prev,
        migrate: {
          loading: false,
          message: result.success
            ? `${result.message}${result.note ? ` Note: ${result.note}` : ''}`
            : (result.error || result.details || 'Migration failed'),
          success: result.success
        }
      }));

      setTimeout(() => {
        setSolrStatus(prev => ({
          ...prev,
          migrate: { loading: false, message: '', success: undefined }
        }));
      }, 10000); // Longer timeout for migration messages
    } catch (error: any) {
      setSolrStatus(prev => ({
        ...prev,
        migrate: {
          loading: false,
          message: error.message || 'Network error occurred',
          success: false
        }
      }));

      setTimeout(() => {
        setSolrStatus(prev => ({
          ...prev,
          migrate: { loading: false, message: '', success: undefined }
        }));
      }, 10000);
    }
  };

  // Load status on component mount
  useEffect(() => {
    loadSearchEngineStatus();
  }, []);

  return (
    <div className="space-y-6">
      {/* Search Management */}
      <div className="theme-card theme-shadow rounded-lg p-6">
        <h2 className="text-xl font-semibold theme-header mb-4">Search Management</h2>
        <p className="theme-text mb-6">
          Manage Solr indices for stories and authors. Use these tools if search isn't returning expected results.
        </p>

        <div className="space-y-6">
          {/* Current Status */}
          <div className="border theme-border rounded-lg p-4">
            <h3 className="text-lg font-semibold theme-header mb-3">Search Status</h3>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm">
              <div className="flex justify-between">
                <span>Solr:</span>
                <span className={`font-medium ${searchEngineStatus.solrAvailable ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}`}>
                  {searchEngineStatus.solrAvailable ? 'Available' : 'Unavailable'}
                </span>
              </div>
            </div>
          </div>

          {/* Search Operations */}
          <div className="border theme-border rounded-lg p-4">
            <h3 className="text-lg font-semibold theme-header mb-3">Search Operations</h3>
            <p className="text-sm theme-text mb-4">
              Perform maintenance operations on search indices. Use these if search isn't returning expected results.
            </p>

            <div className="flex flex-col sm:flex-row gap-3 mb-4">
              <Button
                onClick={handleSolrReindex}
                disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || solrStatus.migrate.loading || !searchEngineStatus.solrAvailable}
                loading={solrStatus.reindex.loading}
                variant="ghost"
                className="flex-1"
              >
                {solrStatus.reindex.loading ? 'Reindexing...' : '🔄 Reindex All'}
              </Button>
              <Button
                onClick={handleSolrRecreate}
                disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || solrStatus.migrate.loading || !searchEngineStatus.solrAvailable}
                loading={solrStatus.recreate.loading}
                variant="secondary"
                className="flex-1"
              >
                {solrStatus.recreate.loading ? 'Recreating...' : '🏗️ Recreate Indices'}
              </Button>
            </div>

            {/* Library Migration Section */}
            <div className="border-t theme-border pt-4">
              <h4 className="text-md font-medium theme-header mb-2">Library Separation Migration</h4>
              <p className="text-sm theme-text mb-3">
                Migrate Solr to support proper library separation. This ensures search results are isolated between different libraries (password-based access).
              </p>
              <Button
                onClick={handleLibraryMigration}
                disabled={solrStatus.reindex.loading || solrStatus.recreate.loading || solrStatus.migrate.loading || !searchEngineStatus.solrAvailable}
                loading={solrStatus.migrate.loading}
                variant="primary"
                className="w-full sm:w-auto"
              >
                {solrStatus.migrate.loading ? 'Migrating...' : '🔒 Migrate Library Schema'}
              </Button>
            </div>

            {/* Status Messages */}
            {solrStatus.reindex.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                solrStatus.reindex.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {solrStatus.reindex.message}
              </div>
            )}

            {solrStatus.recreate.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                solrStatus.recreate.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {solrStatus.recreate.message}
              </div>
            )}

            {solrStatus.migrate.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                solrStatus.migrate.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {solrStatus.migrate.message}
              </div>
            )}
          </div>

          <div className="text-sm theme-text bg-blue-50 dark:bg-blue-900/20 p-3 rounded-lg">
            <p className="font-medium mb-1">When to use these tools:</p>
            <ul className="text-xs space-y-1 ml-4">
              <li>• <strong>Reindex All:</strong> Refresh all search data while keeping existing schemas (fixes data sync issues)</li>
              <li>• <strong>Recreate Indices:</strong> Delete and rebuild all search indexes from scratch (fixes schema and structure issues)</li>
              <li>• <strong>Migrate Library Schema:</strong> One-time migration to enable library separation (isolates search results by library)</li>
            </ul>
            <div className="mt-2 pt-2 border-t border-blue-200 dark:border-blue-700">
              <p className="font-medium text-xs">⚠️ Library Migration:</p>
              <p className="text-xs">Only run this once to enable library-aware search. Requires Solr schema to support libraryId field.</p>
            </div>
          </div>
        </div>
      </div>

      {/* Storage Management */}
      <div className="theme-card theme-shadow rounded-lg p-6">
        <h2 className="text-xl font-semibold theme-header mb-4">Storage Management</h2>
        <p className="theme-text mb-6">
          Clean up orphaned content images that are no longer referenced in any story. This can help free up disk space.
        </p>

        <div className="space-y-6">
          {/* Image Cleanup Section */}
          <div className="border theme-border rounded-lg p-4">
            <h3 className="text-lg font-semibold theme-header mb-3">🖼️ Content Images Cleanup</h3>
            <p className="text-sm theme-text mb-4">
              Scan for and remove orphaned content images that are no longer referenced in any story content. This includes images from deleted stories and unused downloaded images.
            </p>

            <div className="flex flex-col sm:flex-row gap-3 mb-3">
              <Button
                onClick={handleImageCleanupPreview}
                disabled={cleanupStatus.preview.loading}
                loading={cleanupStatus.preview.loading}
                variant="ghost"
                className="flex-1"
              >
                {cleanupStatus.preview.loading ? 'Scanning...' : 'Preview Cleanup'}
              </Button>
              <Button
                onClick={handleImageCleanupExecute}
                disabled={cleanupStatus.execute.loading || !cleanupStatus.preview.data || cleanupStatus.preview.data.orphanedCount === 0}
                loading={cleanupStatus.execute.loading}
                variant="secondary"
                className="flex-1"
              >
                {cleanupStatus.execute.loading ? 'Cleaning...' : 'Execute Cleanup'}
              </Button>
              {cleanupStatus.preview.message && (
                <Button
                  onClick={() => setCleanupStatus(prev => ({
                    ...prev,
                    preview: { loading: false, message: '', success: undefined, data: undefined }
                  }))}
                  variant="ghost"
                  className="px-4 py-2 text-sm"
                >
                  Clear Preview
                </Button>
              )}
            </div>

            {/* Preview Results */}
            {cleanupStatus.preview.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                cleanupStatus.preview.success
                  ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {cleanupStatus.preview.message}
                {cleanupStatus.preview.data && cleanupStatus.preview.data.hasErrors && (
                  <div className="mt-2 text-xs">
                    <details>
                      <summary className="cursor-pointer font-medium">View Errors ({cleanupStatus.preview.data.errors.length})</summary>
                      <ul className="mt-1 ml-4 space-y-1">
                        {cleanupStatus.preview.data.errors.map((error: string, index: number) => (
                          <li key={index} className="text-red-600 dark:text-red-400">• {error}</li>
                        ))}
                      </ul>
                    </details>
                  </div>
                )}
              </div>
            )}

            {/* Execute Results */}
            {cleanupStatus.execute.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                cleanupStatus.execute.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {cleanupStatus.execute.message}
              </div>
            )}

            {/* Detailed Preview Information */}
            {cleanupStatus.preview.data && cleanupStatus.preview.success && (
              <div className="text-sm theme-text bg-gray-50 dark:bg-gray-800 p-3 rounded border">
                <div className="grid grid-cols-2 gap-3">
                  <div>
                    <span className="font-medium">Orphaned Images:</span> {cleanupStatus.preview.data.orphanedCount}
                  </div>
                  <div>
                    <span className="font-medium">Total Size:</span> {cleanupStatus.preview.data.formattedSize}
                  </div>
                  <div>
                    <span className="font-medium">Empty Folders:</span> {cleanupStatus.preview.data.foldersToDelete}
                  </div>
                  <div>
                    <span className="font-medium">Referenced Images:</span> {cleanupStatus.preview.data.referencedImagesCount}
                  </div>
                </div>

                {/* Detailed File List */}
                {cleanupStatus.preview.data.orphanedFiles && cleanupStatus.preview.data.orphanedFiles.length > 0 && (
                  <div className="mt-4">
                    <details className="cursor-pointer">
                      <summary className="font-medium text-sm theme-header mb-2">
                        📁 View Files to be Deleted ({cleanupStatus.preview.data.orphanedFiles.length})
                      </summary>
                      <div className="mt-3 max-h-96 overflow-y-auto border theme-border rounded">
                        <table className="w-full text-xs">
                          <thead className="bg-gray-100 dark:bg-gray-800 sticky top-0">
                            <tr>
                              <th className="text-left p-2 font-medium">File Name</th>
                              <th className="text-left p-2 font-medium">Size</th>
                              <th className="text-left p-2 font-medium">Story</th>
                              <th className="text-left p-2 font-medium">Status</th>
                            </tr>
                          </thead>
                          <tbody>
                            {cleanupStatus.preview.data.orphanedFiles.map((file: any, index: number) => (
                              <tr key={index} className="border-t theme-border hover:bg-gray-50 dark:hover:bg-gray-800">
                                <td className="p-2">
                                  <div
                                    className={`truncate max-w-xs ${isImageFile(file.fileName) ? 'cursor-pointer text-blue-600 dark:text-blue-400' : ''}`}
                                    title={file.fileName}
                                    onMouseEnter={isImageFile(file.fileName) ? (e) => handleImageHover(file.filePath, file.fileName, e) : undefined}
                                    onMouseMove={isImageFile(file.fileName) ? (e) => setMousePosition({ x: e.clientX, y: e.clientY }) : undefined}
                                    onMouseLeave={isImageFile(file.fileName) ? handleImageLeave : undefined}
                                  >
                                    {isImageFile(file.fileName) && '🖼️ '}{file.fileName}
                                  </div>
                                  <div className="text-xs text-gray-500 truncate max-w-xs" title={file.filePath}>
                                    {file.filePath}
                                  </div>
                                </td>
                                <td className="p-2">{file.formattedSize}</td>
                                <td className="p-2">
                                  {file.storyExists && file.storyTitle ? (
                                    <a
                                      href={`/stories/${file.storyId}`}
                                      className="text-blue-600 dark:text-blue-400 hover:underline truncate max-w-xs block"
                                      title={file.storyTitle}
                                    >
                                      {file.storyTitle}
                                    </a>
                                  ) : file.storyId !== 'unknown' && file.storyId !== 'error' ? (
                                    <span className="text-gray-500" title={`Story ID: ${file.storyId}`}>
                                      Deleted Story
                                    </span>
                                  ) : (
                                    <span className="text-gray-400">Unknown</span>
                                  )}
                                </td>
                                <td className="p-2">
                                  {file.storyExists ? (
                                    <span className="text-orange-600 dark:text-orange-400 text-xs">Orphaned</span>
                                  ) : file.storyId !== 'unknown' && file.storyId !== 'error' ? (
                                    <span className="text-red-600 dark:text-red-400 text-xs">Story Deleted</span>
                                  ) : (
                                    <span className="text-gray-500 text-xs">Unknown Folder</span>
                                  )}
                                </td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                      </div>
                    </details>
                  </div>
                )}
              </div>
            )}
          </div>

          <div className="text-sm theme-text bg-blue-50 dark:bg-blue-900/20 p-3 rounded-lg">
            <p className="font-medium mb-1">📝 How it works:</p>
            <ul className="text-xs space-y-1 ml-4">
              <li>• <strong>Preview:</strong> Scans all stories to find images no longer referenced in content</li>
              <li>• <strong>Execute:</strong> Permanently deletes orphaned images and empty story directories</li>
              <li>• <strong>Safe:</strong> Only removes images not found in any story content</li>
              <li>• <strong>Backup recommended:</strong> Consider backing up before large cleanups</li>
            </ul>
          </div>

          {/* EPUB Image Migration Section */}
          <div className="border theme-border rounded-lg p-4">
            <h3 className="text-lg font-semibold theme-header mb-3">📦 EPUB Image Migration</h3>
            <p className="text-sm theme-text mb-4">
              Move images from EPUB imports into the correct story subfolders. These images are still
              referenced by stories and display correctly, but were placed flat in the content directory
              due to an import bug. Run this once to reorganise them.
            </p>

            <div className="flex flex-col sm:flex-row gap-3 mb-3">
              <Button
                onClick={handleEpubMigrationPreview}
                disabled={migrationStatus.preview.loading || migrationStatus.execute.loading}
                loading={migrationStatus.preview.loading}
                variant="ghost"
                className="flex-1"
              >
                {migrationStatus.preview.loading ? 'Scanning...' : 'Preview Migration'}
              </Button>
              <Button
                onClick={handleEpubMigrationExecute}
                disabled={
                  migrationStatus.execute.loading ||
                  !migrationStatus.preview.data ||
                  migrationStatus.preview.data.movedFiles?.filter((f: any) => f.action !== 'unmatched').length === 0
                }
                loading={migrationStatus.execute.loading}
                variant="secondary"
                className="flex-1"
              >
                {migrationStatus.execute.loading ? 'Migrating...' : 'Execute Migration'}
              </Button>
              {migrationStatus.preview.data && (
                <Button
                  onClick={() => setMigrationStatus(prev => ({
                    ...prev,
                    preview: { loading: false, message: '', success: undefined, data: undefined }
                  }))}
                  variant="ghost"
                  className="px-4 py-2 text-sm"
                >
                  Clear Preview
                </Button>
              )}
            </div>

            {migrationStatus.preview.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                migrationStatus.preview.success
                  ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {migrationStatus.preview.message}
              </div>
            )}

            {migrationStatus.execute.message && (
              <div className={`text-sm p-3 rounded mb-3 ${
                migrationStatus.execute.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {migrationStatus.execute.message}
              </div>
            )}

            {migrationStatus.preview.data && migrationStatus.preview.success && (
              <div className="text-sm theme-text bg-gray-50 dark:bg-gray-800 p-3 rounded border">
                <div className="grid grid-cols-2 gap-3 mb-3">
                  <div>
                    <span className="font-medium">To Move:</span>{' '}
                    {migrationStatus.preview.data.movedFiles?.filter((f: any) => f.action !== 'unmatched').length ?? 0}
                  </div>
                  <div>
                    <span className="font-medium">Unmatched:</span>{' '}
                    {migrationStatus.preview.data.unmatchedCount}
                  </div>
                </div>

                {migrationStatus.preview.data.movedFiles?.length > 0 && (
                  <details>
                    <summary className="cursor-pointer font-medium text-sm theme-header mb-2">
                      📁 View Files ({migrationStatus.preview.data.movedFiles.length})
                    </summary>
                    <div className="mt-3 max-h-80 overflow-y-auto border theme-border rounded">
                      <table className="w-full text-xs">
                        <thead className="bg-gray-100 dark:bg-gray-800 sticky top-0">
                          <tr>
                            <th className="text-left p-2 font-medium">File Name</th>
                            <th className="text-left p-2 font-medium">Size</th>
                            <th className="text-left p-2 font-medium">Story</th>
                            <th className="text-left p-2 font-medium">Action</th>
                          </tr>
                        </thead>
                        <tbody>
                          {migrationStatus.preview.data.movedFiles.map((file: any, index: number) => (
                            <tr key={index} className="border-t theme-border hover:bg-gray-50 dark:hover:bg-gray-800">
                              <td className="p-2">
                                <div className="truncate max-w-xs" title={file.fileName}>
                                  🖼️ {file.fileName}
                                </div>
                              </td>
                              <td className="p-2">{file.formattedSize}</td>
                              <td className="p-2">
                                {file.storyTitle ? (
                                  <a
                                    href={`/stories/${file.storyId}`}
                                    className="text-blue-600 dark:text-blue-400 hover:underline truncate max-w-xs block"
                                    title={file.storyTitle}
                                  >
                                    {file.storyTitle}
                                  </a>
                                ) : (
                                  <span className="text-gray-400">No match</span>
                                )}
                              </td>
                              <td className="p-2">
                                {file.action === 'move' && <span className="text-blue-600 dark:text-blue-400">Move</span>}
                                {file.action === 'copy' && <span className="text-purple-600 dark:text-purple-400">Copy</span>}
                                {file.action === 'unmatched' && <span className="text-gray-500">Skip</span>}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </details>
                )}
              </div>
            )}

            <div className="text-sm theme-text bg-blue-50 dark:bg-blue-900/20 p-3 rounded-lg mt-3">
              <p className="font-medium mb-1">ℹ️ Notes:</p>
              <ul className="text-xs space-y-1 ml-4">
                <li>• <strong>Safe to run multiple times</strong> — after migration, no flat images remain and the scan returns zero</li>
                <li>• <strong>Unmatched files</strong> have no story reference and are left in place — use the orphaned cleanup to remove them</li>
                <li>• Story content URLs are updated automatically so images continue to display correctly</li>
              </ul>
            </div>
          </div>
        </div>
      </div>

      {/* Database Management */}
      <div className="theme-card theme-shadow rounded-lg p-6">
        <h2 className="text-xl font-semibold theme-header mb-4">Database Management</h2>
        <p className="theme-text mb-6">
          Backup, restore, or clear your StoryCove database and files. These comprehensive operations include both your data and uploaded images.
        </p>

        <div className="space-y-6">
          {/* Complete Backup Section */}
          <div className="border theme-border rounded-lg p-4 border-blue-200 dark:border-blue-800">
            <h3 className="text-lg font-semibold theme-header mb-3">📦 Create Backup</h3>
            <p className="text-sm theme-text mb-3">
              Creates a complete backup saved on the server. The backup includes your database AND all uploaded files (cover images, avatars).
            </p>
            <Button
              onClick={handleCompleteBackup}
              disabled={databaseStatus.completeBackup.loading}
              loading={databaseStatus.completeBackup.loading}
              variant="primary"
              className="w-full sm:w-auto"
            >
              {databaseStatus.completeBackup.loading ? 'Creating Backup...' : 'Create Backup'}
            </Button>

            {databaseStatus.completeBackup.loading && databaseStatus.completeBackup.progress !== undefined && (
              <div className="mt-3">
                <div className="flex justify-between text-sm theme-text mb-1">
                  <span>Progress</span>
                  <span>{databaseStatus.completeBackup.progress}%</span>
                </div>
                <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5">
                  <div
                    className="bg-blue-600 dark:bg-blue-500 h-2.5 rounded-full transition-all duration-300"
                    style={{ width: `${databaseStatus.completeBackup.progress}%` }}
                  ></div>
                </div>
              </div>
            )}

            {databaseStatus.completeBackup.message && (
              <div className={`text-sm p-2 rounded mt-3 ${
                databaseStatus.completeBackup.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : databaseStatus.completeBackup.success === false
                  ? 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
                  : 'bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200'
              }`}>
                {databaseStatus.completeBackup.message}
              </div>
            )}
          </div>

          {/* Backup List / Restore Section */}
          <div className="border theme-border rounded-lg p-4 border-blue-200 dark:border-blue-800">
            <div className="flex items-center justify-between mb-3">
              <h3 className="text-lg font-semibold theme-header">📋 Backups</h3>
              <button
                onClick={loadBackups}
                disabled={backupList.loading}
                className="text-sm theme-text opacity-70 hover:opacity-100 flex items-center gap-1"
                title="Refresh backup list"
              >
                <span className={backupList.loading ? 'animate-spin' : ''}>↻</span>
                Refresh
              </button>
            </div>
            <p className="text-sm theme-text mb-4">
              Backups are stored on the server. To transfer a backup to another server, download it and place it in the server's backup directory — it will appear here automatically.
            </p>

            {restoreStatus.message && (
              <div className={`text-sm p-2 rounded mb-3 ${
                restoreStatus.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : restoreStatus.success === false
                  ? 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
                  : 'bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200'
              }`}>
                {restoreStatus.loading && (
                  <span className="inline-block animate-spin mr-2">↻</span>
                )}
                {restoreStatus.message}
              </div>
            )}

            {backupList.error && (
              <div className="text-sm p-2 rounded mb-3 bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200">
                {backupList.error}
              </div>
            )}

            {backupList.loading && backupList.backups.length === 0 ? (
              <div className="text-sm theme-text flex items-center gap-2 py-4">
                <div className="animate-spin w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full"></div>
                Loading backups...
              </div>
            ) : backupList.backups.length === 0 ? (
              <p className="text-sm theme-text opacity-60 py-4 text-center">No backups found. Create your first backup above.</p>
            ) : (
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b theme-border text-left">
                      <th className="pb-2 pr-4 font-medium theme-text">Date</th>
                      <th className="pb-2 pr-4 font-medium theme-text">Origin</th>
                      <th className="pb-2 pr-4 font-medium theme-text">Size</th>
                      <th className="pb-2 font-medium theme-text text-right">Actions</th>
                    </tr>
                  </thead>
                  <tbody>
                    {backupList.backups.map(backup => (
                      <tr key={backup.filename} className="border-b theme-border last:border-0">
                        <td className="py-2 pr-4 theme-text">
                          <div>{new Date(backup.createdAt).toLocaleDateString()}</div>
                          <div className="text-xs opacity-60">{new Date(backup.createdAt).toLocaleTimeString()}</div>
                        </td>
                        <td className="py-2 pr-4">
                          <span className={`inline-block text-xs px-2 py-0.5 rounded-full font-medium ${
                            backup.origin === 'MANUAL'
                              ? 'bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300'
                              : backup.origin === 'AUTO'
                              ? 'bg-green-100 dark:bg-green-900/40 text-green-700 dark:text-green-300'
                              : 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400'
                          }`}>
                            {backup.origin === 'MANUAL' ? 'Manual' : backup.origin === 'AUTO' ? 'Automatic' : 'Unknown'}
                          </span>
                        </td>
                        <td className="py-2 pr-4 theme-text opacity-70 text-xs">
                          {backup.sizeBytes >= 1024 * 1024
                            ? `${(backup.sizeBytes / 1024 / 1024).toFixed(1)} MB`
                            : `${(backup.sizeBytes / 1024).toFixed(0)} KB`}
                        </td>
                        <td className="py-2">
                          <div className="flex items-center gap-2 justify-end">
                            <button
                              onClick={() => handleRestoreFromFile(backup.filename)}
                              disabled={restoreStatus.loading}
                              className="text-xs px-2 py-1 rounded border theme-border theme-text hover:bg-orange-50 dark:hover:bg-orange-900/20 hover:border-orange-300 dark:hover:border-orange-700 disabled:opacity-40"
                              title="Restore this backup"
                            >
                              Restore
                            </button>
                            <button
                              onClick={() => handleDownloadBackupFile(backup.filename)}
                              className="text-xs px-2 py-1 rounded border theme-border theme-text hover:bg-blue-50 dark:hover:bg-blue-900/20 hover:border-blue-300 dark:hover:border-blue-700"
                              title="Download this backup"
                            >
                              ⬇
                            </button>
                            <button
                              onClick={() => handleDeleteBackupFile(backup.filename)}
                              disabled={restoreStatus.loading}
                              className="text-xs px-2 py-1 rounded border border-red-200 dark:border-red-800 text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 disabled:opacity-40"
                              title="Delete this backup"
                            >
                              ✕
                            </button>
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>

          {/* Clear Everything Section */}
          <div className="border theme-border rounded-lg p-4 border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/10">
            <h3 className="text-lg font-semibold theme-header mb-3">🗑️ Clear Everything</h3>
            <p className="text-sm theme-text mb-3">
              <strong className="text-red-600 dark:text-red-400">⚠️ Danger Zone:</strong> This will permanently delete ALL data from your database AND all uploaded files (cover images, avatars). Everything will be completely removed. This action cannot be undone!
            </p>
            <Button
              onClick={handleCompleteClear}
              disabled={databaseStatus.completeClear.loading}
              loading={databaseStatus.completeClear.loading}
              variant="secondary"
              className="w-full sm:w-auto bg-red-700 hover:bg-red-800 text-white border-red-700"
            >
              {databaseStatus.completeClear.loading ? 'Clearing Everything...' : 'Clear Everything'}
            </Button>
            {databaseStatus.completeClear.message && (
              <div className={`text-sm p-2 rounded mt-3 ${
                databaseStatus.completeClear.success
                  ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200'
                  : 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'
              }`}>
                {databaseStatus.completeClear.message}
              </div>
            )}
          </div>

          <div className="text-sm theme-text bg-blue-50 dark:bg-blue-900/20 p-3 rounded-lg">
            <p className="font-medium mb-1">💡 Best Practices:</p>
            <ul className="text-xs space-y-1 ml-4">
              <li>• <strong>Always backup</strong> before performing restore or clear operations</li>
              <li>• <strong>Cross-server transfer:</strong> download a backup and place it in the backup directory of the other server — it appears in this list automatically</li>
              <li>• <strong>Backup files (.zip)</strong> contain both database and all uploaded files</li>
              <li>• <strong>Automatic backups</strong> are created daily at 4 AM when content has changed (up to 10 kept)</li>
            </ul>
          </div>
        </div>
      </div>

      {/* Image Preview Overlay */}
      {hoveredImage && (
        <div
          className="fixed pointer-events-none z-50 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg shadow-xl p-2 max-w-sm"
          style={{
            left: mousePosition.x + 10,
            top: mousePosition.y - 100,
            transform: mousePosition.x > window.innerWidth - 300 ? 'translateX(-100%)' : 'none'
          }}
        >
          <img
            src={hoveredImage.src}
            alt={hoveredImage.alt}
            className="max-w-full max-h-64 object-contain rounded"
            onError={() => {
              // Hide preview if image fails to load
              setHoveredImage(null);
            }}
          />
          <div className="text-xs theme-text mt-1 truncate">
            {hoveredImage.alt}
          </div>
        </div>
      )}
    </div>
  );
}