import React, { useState, useCallback, useEffect } from 'react';
import { useAuth } from './services/authService';
import { CsvInputRow, QueueItem, ResultRow, JobHistoryItem, ProcessedResult, BatchError } from './types';
import FileUpload from './components/FileUpload';
import ResultsTable from './components/ResultsTable';
import SignInPage from './components/SignInPage';
import { runWorkflow } from './services/difyService';
import { CheckCircleIcon, XCircleIcon, ClockIcon, UploadIcon, RocketLaunchIcon, PlusIcon, HistoryIcon, DocumentTextIcon, TrashIcon } from './components/Icons';
import Spinner from './components/Spinner';

// --- UTILS & HOOKS (in-file for simplicity) ---

const generateUUID = (): string => {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
};

const delay = (ms: number) => new Promise(res => setTimeout(res, ms));

// Calculate approximate storage size for job results
const estimateStorageSize = (results: ResultRow[]): number => {
    return JSON.stringify(results).length;
};

// Maximum storage size per job (500KB)
const MAX_JOB_STORAGE_SIZE = 500 * 1024;

// Enhanced localStorage hook with better error handling and data validation
function useLocalStorage<T>(key: string, initialValue: T): [T, React.Dispatch<React.SetStateAction<T>>] {
    const [storedValue, setStoredValue] = useState<T>(() => {
        try {
            const item = window.localStorage.getItem(key);
            if (item) {
                const parsed = JSON.parse(item);
                
                // Enhanced validation for different data types
                if (Array.isArray(parsed)) {
                    // Filter out old items that had the 'results' property which caused storage errors.
                    let cleanHistory = parsed.filter(p => typeof p === 'object' && p !== null && !p.hasOwnProperty('results'));
                    
                    // Remove duplicates based on ID if it's a history array
                    if (key === 'ace-copywriting-history' && cleanHistory.length > 0) {
                        const uniqueHistory = cleanHistory.reduce((acc: any[], current: any) => {
                            const existingIndex = acc.findIndex(item => item.id === current.id);
                            if (existingIndex === -1) {
                                acc.push(current);
                            }
                            return acc;
                        }, []);
                        cleanHistory = uniqueHistory;
                    }
                    
                    return cleanHistory;
                }
                return parsed;
            }
            return initialValue;
        } catch (error) {
            console.error('Error reading from localStorage, resetting to initial value.', error);
            window.localStorage.removeItem(key); // Clear corrupted item
            return initialValue;
        }
    });

    const setValue: React.Dispatch<React.SetStateAction<T>> = useCallback((value) => {
        try {
            setStoredValue(prev => {
                const valueToStore = value instanceof Function ? value(prev) : value;
                
                // Check storage quota before saving
                const serialized = JSON.stringify(valueToStore);
                if (serialized.length > 5 * 1024 * 1024) { // 5MB limit
                    console.warn('Data too large for localStorage, truncating...');
                    // For history, keep only the most recent items
                    if (Array.isArray(valueToStore) && key === 'ace-copywriting-history') {
                        const truncated = (valueToStore as any[]).slice(0, 5); // Keep only 5 most recent
                        window.localStorage.setItem(key, JSON.stringify(truncated));
                        return truncated as T;
                    }
                }
                
                window.localStorage.setItem(key, serialized);
                return valueToStore;
            });
        } catch (error) {
            console.error('Error writing to localStorage', error);
            // If quota exceeded, try to clear old data and retry
            if (error instanceof Error && error.name === 'QuotaExceededError') {
                try {
                    // Clear old history items to make space
                    if (key === 'ace-copywriting-history') {
                        const currentHistory = window.localStorage.getItem(key);
                        if (currentHistory) {
                            const parsed = JSON.parse(currentHistory);
                            if (Array.isArray(parsed) && parsed.length > 3) {
                                const truncated = parsed.slice(0, 3); // Keep only 3 most recent
                                window.localStorage.setItem(key, JSON.stringify(truncated));
                                setStoredValue(truncated as T);
                            }
                        }
                    }
                } catch (clearError) {
                    console.error('Failed to clear storage for new data', clearError);
                }
            }
        }
    }, [key]);
    
    return [storedValue, setValue];
}

// Hook for user preferences
function useUserPreferences() {
    const [preferences, setPreferences] = useLocalStorage('ace-copywriting-preferences', {
        autoSave: true,
        maxHistoryItems: 10,
        showDebugInfo: false,
        defaultExportFormat: 'csv' as 'csv' | 'pdf' | 'docx' | 'json',
        theme: 'dark' as 'dark' | 'light'
    });
    
    return [preferences, setPreferences] as const;
}

// Hook for session data (cleared on browser close)
function useSessionStorage<T>(key: string, initialValue: T): [T, React.Dispatch<React.SetStateAction<T>>] {
    const [storedValue, setStoredValue] = useState<T>(() => {
        try {
            const item = window.sessionStorage.getItem(key);
            return item ? JSON.parse(item) : initialValue;
        } catch (error) {
            console.error('Error reading from sessionStorage', error);
            return initialValue;
        }
    });

    const setValue: React.Dispatch<React.SetStateAction<T>> = useCallback((value) => {
        try {
            setStoredValue(prev => {
                const valueToStore = value instanceof Function ? value(prev) : value;
                window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
                return valueToStore;
            });
        } catch (error) {
            console.error('Error writing to sessionStorage', error);
        }
    }, [key]);
    
    return [storedValue, setValue];
}


// --- TYPES ---

type ProcessingStatus = 'idle' | 'processing' | 'completed' | 'error';
type ViewState = 
    | { type: 'welcome' }
    | { type: 'new_job' }
    | { type: 'view_history'; jobId: string };

// --- CONSTANTS ---
const MAX_HISTORY_ITEMS = 10;

// --- MAIN COMPONENT ---

const App: React.FC = () => {
    const { user, logout } = useAuth();
    const [history, setHistory] = useLocalStorage<JobHistoryItem[]>('ace-copywriting-history', []);
    const [preferences, setPreferences] = useUserPreferences();
    const [view, setView] = useState<ViewState>(() => history.length > 0 ? { type: 'new_job' } : { type: 'welcome' });

    // State for the currently active processing job - persist in sessionStorage
    const [jobId, setJobId] = useSessionStorage<string | null>('ace-current-job-id', null);
    const [filename, setFilename] = useSessionStorage<string>('ace-current-filename', '');
    const [queue, setQueue] = useSessionStorage<QueueItem[]>('ace-current-queue', []);
    const [results, setResults] = useSessionStorage<ResultRow[]>('ace-current-results', []);
    const [status, setStatus] = useSessionStorage<ProcessingStatus>('ace-current-status', 'idle');
    const [error, setError] = useSessionStorage<string | null>('ace-current-error', null);
    const [deleteConfirmId, setDeleteConfirmId] = useState<string | null>(null);

    // New: capture all user-facing errors and show a details modal - persist in sessionStorage
    const [errors, setErrors] = useSessionStorage<BatchError[]>('ace-current-errors', []);
    const [showErrorDetails, setShowErrorDetails] = useState(false);
    const [expandedDebugIndex, setExpandedDebugIndex] = useState<number | null>(null);

    // Auto-save current job state when it changes
    useEffect(() => {
        if (preferences.autoSave && jobId) {
            const jobState = {
                jobId,
                filename,
                queue,
                results,
                status,
                error,
                errors,
                timestamp: new Date().toISOString()
            };
            
            try {
                window.sessionStorage.setItem('ace-current-job-state', JSON.stringify(jobState));
            } catch (error) {
                console.warn('Failed to auto-save job state:', error);
            }
        }
    }, [preferences.autoSave, jobId, filename, queue, results, status, error, errors]);

    // Restore job state on app load
    useEffect(() => {
        try {
            const savedState = window.sessionStorage.getItem('ace-current-job-state');
            if (savedState) {
                const jobState = JSON.parse(savedState);
                const stateAge = Date.now() - new Date(jobState.timestamp).getTime();
                const maxAge = 24 * 60 * 60 * 1000; // 24 hours
                
                // Only restore if state is recent
                if (stateAge < maxAge) {
                    setJobId(jobState.jobId);
                    setFilename(jobState.filename);
                    setQueue(jobState.queue || []);
                    setResults(jobState.results || []);
                    setStatus(jobState.status || 'idle');
                    setError(jobState.error);
                    setErrors(jobState.errors || []);
                    
                    // Set appropriate view based on restored state
                    if (jobState.status === 'completed' && jobState.results?.length > 0) {
                        setView({ type: 'new_job' }); // Show results view
                    } else if (jobState.status === 'processing') {
                        setView({ type: 'new_job' }); // Show processing view
                    }
                } else {
                    // Clear old state
                    window.sessionStorage.removeItem('ace-current-job-state');
                }
            }
        } catch (error) {
            console.warn('Failed to restore job state:', error);
            // Clear corrupted state
            window.sessionStorage.removeItem('ace-current-job-state');
        }
    }, []);

    const resetNewJobState = useCallback(() => {
        setJobId(generateUUID());
        setFilename('');
        setQueue([]);
        setResults([]);
        setStatus('idle');
        setError(null);
        setErrors([]);
        setShowErrorDetails(false);
        
        // Clear session storage for new job
        window.sessionStorage.removeItem('ace-current-job-state');
    }, [setJobId, setFilename, setQueue, setResults, setStatus, setError, setErrors]);

    const handleStartNewJob = () => {
        resetNewJobState();
        setView({ type: 'new_job' });
    };

    const handleDeleteJob = (jobId: string) => {
        setHistory(prevHistory => prevHistory.filter(h => h.id !== jobId));
        setDeleteConfirmId(null);
        
        // If we're currently viewing the deleted job, navigate back to new job
        if (view.type === 'view_history' && view.jobId === jobId) {
            setView({ type: 'new_job' });
        }
    };

    // Enhanced file parsing with better error handling
    const handleFileParsed = useCallback((data: CsvInputRow[], file: File) => {
        // Ensure we have a jobId for this processing session
        if (!jobId) {
            setJobId(generateUUID());
        }
        setFilename(file.name);
        const initialQueue = data.map((row, index) => ({
            id: index,
            data: row,
            status: 'pending' as const,
        }));
        setQueue(initialQueue);
        setError(null);
        setErrors([]);
        
        // Save file info to history for reference
        const fileInfo = {
            filename: file.name,
            size: file.size,
            lastModified: file.lastModified,
            rowCount: data.length
        };
        
        try {
            const fileHistory = JSON.parse(localStorage.getItem('ace-file-history') || '[]');
            const updatedHistory = [fileInfo, ...fileHistory.slice(0, 9)]; // Keep last 10 files
            localStorage.setItem('ace-file-history', JSON.stringify(updatedHistory));
        } catch (error) {
            console.warn('Failed to save file history:', error);
        }
    }, [jobId, setJobId, setFilename, setQueue, setError, setErrors]);
    
    const handleStartProcessing = async () => {
        console.log('Start processing clicked. JobId:', jobId, 'Queue length:', queue.length);
        if (!jobId || queue.length === 0) {
            console.log('Processing aborted - missing jobId or empty queue');
            return;
        }
        console.log('Starting processing...');
        setStatus('processing');
        setError(null);
        setErrors([]);
        setResults([]); // Clear previous results
        
        const newResults: ResultRow[] = [];

        for (const [index, item] of queue.entries()) {
            setQueue(prev => prev.map(q => q.id === item.id ? { ...q, status: 'processing' } : q));
            try {
                const processedData: ProcessedResult = await runWorkflow(item.data);
                const resultRow: ResultRow = { ...item.data, ...processedData, id: item.id };
                newResults.push(resultRow);
                setResults(prev => [...prev, resultRow]); // Add one result at a time
                setQueue(prev => prev.map(q => q.id === item.id ? { ...q, status: 'completed' } : q));
            } catch (e) {
                const msg = e instanceof Error ? e.message : 'An unknown error occurred';
                setQueue(prev => prev.map(q => q.id === item.id ? { ...q, status: 'failed', error: msg } : q));
                setError('Some rows failed during processing.');
                setErrors(prev => ([
                    ...prev,
                    { row: item.id + 1, code: e instanceof Error ? (e as any).code || 'UNKNOWN' : 'UNKNOWN', message: msg, at: (e as any).at || 'unknown', suggestion: 'Retry later or check input for this row.' }
                ]));
            }

            // Add a delay between requests to avoid overwhelming the API.
            if (index < queue.length - 1) {
                await delay(500); // 0.5 second pause
            }
        }
        setStatus('completed');
    };
    
    // Effect to save job summary to history when completed
    useEffect(() => {
        console.log('History save effect triggered:', { status, jobId, queueLength: queue.length, resultsLength: results.length });
        if (status === 'completed' && jobId) {
            console.log('Saving job to history:', { jobId, filename, queueLength: queue.length, resultsLength: results.length });
            const completedCount = queue.filter(q => q.status === 'completed').length;
            const failedCount = queue.filter(q => q.status === 'failed').length;
            
            setHistory(prevHistory => {
                // Check if this job is already in history to prevent duplicates
                const existingIndex = prevHistory.findIndex(h => h.id === jobId);
                if (existingIndex !== -1) {
                    return prevHistory; // Already exists, don't add again
                }

                // Check if results are too large for storage
                const storageSize = estimateStorageSize(results);
                const shouldStoreResults = storageSize <= MAX_JOB_STORAGE_SIZE;
                
                if (!shouldStoreResults) {
                    console.warn(`Job results too large for storage (${Math.round(storageSize / 1024)}KB). Only storing summary.`);
                }

                const newHistoryItem: JobHistoryItem = {
                    id: jobId,
                    filename,
                    date: new Date().toISOString(),
                    totalRows: queue.length,
                    completedCount,
                    failedCount,
                    results: shouldStoreResults ? [...results] : undefined, // Store results if not too large
                };

                const updatedHistory = [newHistoryItem, ...prevHistory];
                
                // Prune history to the maximum allowed size from preferences
                const maxItems = preferences.maxHistoryItems || 10;
                const prunedHistory = updatedHistory.slice(0, maxItems);
                
                console.log('Job saved to history successfully:', newHistoryItem);
                return prunedHistory;
            });
            
            // Clear session storage after successful save
            window.sessionStorage.removeItem('ace-current-job-state');
        }
    }, [status, jobId, filename, queue.length, results, setHistory, preferences.maxHistoryItems]);

    // Cleanup old history items periodically
    useEffect(() => {
        const cleanupHistory = () => {
            setHistory(prevHistory => {
                const maxAge = 30 * 24 * 60 * 60 * 1000; // 30 days
                const now = Date.now();
                const filtered = prevHistory.filter(item => {
                    const itemAge = now - new Date(item.date).getTime();
                    return itemAge < maxAge;
                });
                
                if (filtered.length !== prevHistory.length) {
                    console.log(`Cleaned up ${prevHistory.length - filtered.length} old history items`);
                }
                
                return filtered;
            });
        };

        // Clean up on app start
        cleanupHistory();
        
        // Set up periodic cleanup (every hour)
        const interval = setInterval(cleanupHistory, 60 * 60 * 1000);
        
        return () => clearInterval(interval);
    }, [setHistory]);
    
    // --- RENDER ---

    const renderStatusIcon = (itemStatus: QueueItem['status']) => {
        switch (itemStatus) {
            case 'pending': return <ClockIcon className="w-5 h-5 text-gray-400 flex-shrink-0" />;
            case 'processing': return <Spinner />;
            case 'completed': return <CheckCircleIcon className="w-5 h-5 text-green-400 flex-shrink-0" />;
            case 'failed': return <XCircleIcon className="w-5 h-5 text-red-400 flex-shrink-0" />;
        }
    };

    const getActiveJobId = () => {
        if (view.type === 'new_job' && jobId) return jobId;
        if (view.type === 'view_history') return view.jobId;
        return null;
    }

    const ErrorDetailsModal: React.FC<{ onClose: () => void; items: BatchError[] }> = ({ onClose, items }) => (
        <div className="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center p-4 z-50" onClick={onClose}>
            <div className="bg-gray-800 rounded-lg shadow-xl p-6 max-w-2xl w-full" onClick={e => e.stopPropagation()}>
                <div className="flex items-center justify-between mb-4">
                    <h3 className="text-xl font-bold text-white">Processing Errors</h3>
                    <div className="flex items-center gap-2">
                        <button onClick={() => setErrors([])} className="text-xs px-2 py-1 bg-gray-700 hover:bg-gray-600 rounded text-gray-200">Clear</button>
                        <button onClick={onClose} className="text-gray-300 hover:text-white">Close</button>
                    </div>
                </div>
                {items.length === 0 ? (
                    <p className="text-gray-300">No errors recorded.</p>
                ) : (
                    <div className="max-h-80 overflow-y-auto divide-y divide-gray-700">
                        {items.map((e, idx) => (
                            <div key={idx} className="py-3 text-sm">
                                <div className="flex items-start justify-between">
                                    <div>
                                        <div className="text-white font-medium">{e.row ? `Row ${e.row}` : 'General'} — {e.code}</div>
                                        <div className="text-gray-300 mt-1">{e.message}</div>
                                        {e.suggestion && <div className="text-gray-400 mt-1">Suggestion: {e.suggestion}</div>}
                                        {e.at && <div className="text-gray-500 mt-1 text-xs">Area: {e.at}</div>}
                                    </div>
                                    <button
                                        className="text-xs text-gray-400 hover:text-white"
                                        onClick={() => setErrors(prev => prev.filter((_, i) => i !== idx))}
                                        title="Dismiss this error"
                                    >Dismiss</button>
                                </div>
                                {e.debug && (
                                    <div className="mt-2">
                                        <button
                                            className="text-xs text-blue-300 hover:text-blue-200 underline"
                                            onClick={() => setExpandedDebugIndex(expandedDebugIndex === idx ? null : idx)}
                                        >
                                            {expandedDebugIndex === idx ? 'Hide debug' : 'Show debug'}
                                        </button>
                                        {expandedDebugIndex === idx && (
                                            <div className="mt-2 bg-gray-900 rounded border border-gray-700 p-2">
                                                <pre className="text-xs text-gray-300 whitespace-pre-wrap max-h-48 overflow-auto">{e.debug}</pre>
                                                <button
                                                    className="mt-2 text-xs text-gray-300 hover:text-white underline"
                                                    onClick={() => {
                                                        navigator.clipboard?.writeText(e.debug || '');
                                                    }}
                                                >Copy debug</button>
                                            </div>
                                        )}
                                    </div>
                                )}
                            </div>
                        ))}
                    </div>
                )}
            </div>
        </div>
    );

    const renderMainContent = () => {
        if (view.type === 'welcome') {
            return (
                <div className="text-center">
                    <h1 className="text-4xl font-bold text-white">Welcome to the ACE Copywriting Pipeline</h1>
                    <p className="mt-4 text-lg text-gray-400">Process CSV files, generate optimized copy, and review your job history.</p>
                    <button
                        onClick={handleStartNewJob}
                        className="mt-8 inline-flex items-center gap-2 bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-lg transition-colors duration-200"
                    >
                        <PlusIcon className="w-6 h-6"/> Start Your First Job
                    </button>
                </div>
            );
        }

        if (view.type === 'view_history' && view.jobId) {
            const job = history.find(h => h.id === view.jobId);
            if (!job) return <div className="text-center text-red-400">Job not found in history.</div>;

            // If we have stored results, show them; otherwise show summary
            if (job.results && job.results.length > 0) {
                return <ResultsTable results={job.results} />;
            }

            return (
                 <div className="w-full max-w-4xl mx-auto">
                     <div className="bg-gray-800 p-8 rounded-xl shadow-2xl">
                        <h2 className="text-3xl font-bold text-white truncate" title={job.filename}>{job.filename}</h2>
                        <p className="mt-2 text-md text-gray-400 flex items-center gap-2"><HistoryIcon className="w-5 h-5" /><span>Job processed on {new Date(job.date).toLocaleString()}</span></p>
        
                        <div className="mt-8 grid grid-cols-1 md:grid-cols-3 gap-6 text-center">
                            <div className="bg-gray-700/50 p-6 rounded-lg">
                                <p className="text-sm text-gray-400 uppercase tracking-wider">Total Rows</p>
                                <p className="text-4xl font-semibold text-white mt-1">{job.totalRows}</p>
                            </div>
                            <div className="bg-green-900/40 p-6 rounded-lg">
                                <p className="text-sm text-green-400 uppercase tracking-wider">Succeeded</p>
                                <p className="text-4xl font-semibold text-green-300 mt-1">{job.completedCount}</p>
                            </div>
                             <div className="bg-red-900/40 p-6 rounded-lg">
                                <p className="text-sm text-red-400 uppercase tracking-wider">Failed</p>
                                <p className="text-4xl font-semibold text-red-300 mt-1">{job.failedCount}</p>
                            </div>
                        </div>
        
                        <div className="mt-8 bg-gray-900/50 border border-gray-700 rounded-lg p-4 text-center">
                            <p className="text-gray-300">
                                Detailed results are not available for this job.
                            </p>
                            <p className="text-gray-400 text-sm mt-1">
                                This may be due to job size limitations or legacy storage format.
                            </p>
                        </div>
                     </div>
                </div>
            )
        }
        
        if (view.type === 'new_job') {
            if (status === 'completed') {
                 return <ResultsTable results={results} />;
            }
            if (queue.length === 0) {
                 return <FileUpload onFileParsed={handleFileParsed} onParseError={(msg) => {
                    setError(msg);
                    setErrors(prev => ([...prev, { code: 'CSV_PARSE_ERROR', message: msg, at: 'csv', suggestion: 'Check required columns and CSV formatting.' }]));
                 }} disabled={false} />;
            }
            return (
                <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 w-full">
                    <div className="lg:col-span-1 bg-gray-800 p-6 rounded-xl shadow-lg self-start">
                        <h2 className="text-2xl font-semibold mb-4 text-white">Controls</h2>
                        <div className="space-y-4">
                            <div className="p-4 bg-gray-700 rounded-lg">
                                 <p className="font-medium text-white truncate" title={filename}>{filename}</p>
                                 <p className="text-sm text-gray-300">{queue.length} rows ready for processing.</p>
                            </div>
                            <button
                                onClick={handleStartProcessing}
                                disabled={status === 'processing'}
                                className="w-full flex items-center justify-center gap-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 text-white font-bold py-3 px-4 rounded-lg transition-colors duration-200"
                            >
                               {status === 'processing' ? <><Spinner /> Processing...</> : <><RocketLaunchIcon className="w-5 h-5"/> Start Processing</>}
                            </button>
                            <button
                                onClick={handleStartNewJob}
                                disabled={status === 'processing'}
                                className="w-full flex items-center justify-center gap-2 bg-gray-600 hover:bg-gray-500 disabled:bg-gray-500/50 text-white font-bold py-3 px-4 rounded-lg transition-colors duration-200"
                            >
                                <UploadIcon className="w-5 h-5"/> Upload New File
                            </button>
                        </div>
                    </div>
                    <div className="lg:col-span-2 bg-gray-800 p-6 rounded-xl shadow-lg">
                        <h2 className="text-2xl font-semibold mb-4 text-white">Processing Queue</h2>
                        <div className="space-y-1 max-h-96 overflow-y-auto pr-2">
                            {queue
                                .filter((item, index, arr) => arr.findIndex(q => q.id === item.id) === index) // Remove any runtime duplicates
                                .map(item => (
                                <div key={item.id} className="flex items-center justify-between p-3 bg-gray-700/50 rounded-lg" title={item.error}>
                                    <div className="flex items-center gap-3 overflow-hidden">
                                        {renderStatusIcon(item.status)}
                                        <p className="truncate text-gray-300 text-sm">Row {item.id + 1}: <span className="text-gray-400">{item.data.URL}</span></p>
                                    </div>
                                </div>
                            ))}
                        </div>
                        {status === 'processing' &&
                          <div className="mt-4 text-blue-300">
                            <p className="text-sm">Processed: {results.length}/{queue.length}</p>
                            <div className="w-full bg-gray-700 rounded-full h-2.5 mt-2">
                              <div className="bg-blue-600 h-2.5 rounded-full" style={{ width: `${(results.length / queue.length) * 100}%` }}></div>
                            </div>
                          </div>
                        }
                    </div>
                </div>
            );
        }

        return null;
    };


    const DeleteConfirmationDialog: React.FC<{ jobId: string; filename: string; onConfirm: () => void; onCancel: () => void }> = ({ jobId, filename, onConfirm, onCancel }) => (
        <div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center p-4 z-50" onClick={onCancel}>
            <div className="bg-gray-800 rounded-lg shadow-xl p-6 max-w-md w-full" onClick={e => e.stopPropagation()}>
                <div className="flex items-center gap-3 mb-4">
                    <TrashIcon className="w-6 h-6 text-red-400" />
                    <h3 className="text-xl font-bold text-white">Delete Job</h3>
                </div>
                <p className="text-gray-300 mb-6">
                    Are you sure you want to delete the job for <span className="font-medium text-white">"{filename}"</span>? 
                    This action cannot be undone.
                </p>
                <div className="flex gap-3 justify-end">
                    <button
                        onClick={onCancel}
                        className="px-4 py-2 bg-gray-600 hover:bg-gray-500 text-white rounded-lg transition-colors"
                    >
                        Cancel
                    </button>
                    <button
                        onClick={onConfirm}
                        className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg transition-colors"
                    >
                        Delete
                    </button>
                </div>
            </div>
        </div>
    );

    // Storage management utilities
    const getStorageInfo = () => {
        try {
            const totalSpace = 5 * 1024 * 1024; // 5MB limit
            const usedSpace = new Blob([JSON.stringify(history)]).size;
            const usedPercentage = (usedSpace / totalSpace) * 100;
            
            return {
                usedSpace: Math.round(usedSpace / 1024), // KB
                totalSpace: Math.round(totalSpace / 1024), // KB
                usedPercentage: Math.round(usedPercentage),
                historyCount: history.length,
                maxHistoryItems: preferences.maxHistoryItems
            };
        } catch (error) {
            console.error('Error calculating storage info:', error);
            return null;
        }
    };

    const clearAllData = () => {
        if (window.confirm('Are you sure you want to clear all stored data? This will remove all job history and cannot be undone.')) {
            try {
                // Clear localStorage
                window.localStorage.removeItem('ace-copywriting-history');
                window.localStorage.removeItem('ace-copywriting-preferences');
                window.localStorage.removeItem('ace-file-history');
                
                // Clear sessionStorage
                window.sessionStorage.clear();
                
                // Reset state
                setHistory([]);
                setPreferences({
                    autoSave: true,
                    maxHistoryItems: 10,
                    showDebugInfo: false,
                    defaultExportFormat: 'csv',
                    theme: 'dark'
                });
                
                // Reset current job state
                resetNewJobState();
                setView({ type: 'welcome' });
                
                alert('All data has been cleared successfully.');
            } catch (error) {
                console.error('Error clearing data:', error);
                alert('Error clearing data. Please try refreshing the page.');
            }
        }
    };

    const StorageInfoComponent: React.FC = () => {
        const storageInfo = getStorageInfo();
        
        if (!storageInfo) return null;
        
        return (
            <div className="bg-gray-700/80 backdrop-blur-sm rounded-lg p-3 border border-gray-600">
                <div className="flex items-center justify-between mb-2">
                    <h3 className="text-xs font-semibold text-gray-200">Storage</h3>
                    <button
                        onClick={clearAllData}
                        className="text-xs px-2 py-1 bg-red-600 hover:bg-red-700 text-white rounded transition-colors"
                        title="Clear all stored data"
                    >
                        Clear
                    </button>
                </div>
                <div className="grid grid-cols-2 gap-3 text-xs">
                    <div>
                        <div className="text-gray-400 text-xs">Used</div>
                        <div className="text-white font-medium">{storageInfo.usedSpace}KB</div>
                        <div className="w-full bg-gray-600 rounded-full h-1 mt-1">
                            <div 
                                className={`h-1 rounded-full transition-all ${storageInfo.usedPercentage > 80 ? 'bg-red-500' : storageInfo.usedPercentage > 60 ? 'bg-yellow-500' : 'bg-green-500'}`}
                                style={{ width: `${Math.min(storageInfo.usedPercentage, 100)}%` }}
                            ></div>
                        </div>
                    </div>
                    <div>
                        <div className="text-gray-400 text-xs">History</div>
                        <div className="text-white font-medium">{storageInfo.historyCount}/{storageInfo.maxHistoryItems}</div>
                    </div>
                </div>
                {storageInfo.usedPercentage > 80 && (
                    <div className="text-xs text-yellow-400 mt-2 flex items-center gap-1">
                        <span>⚠️</span>
                        <span>Storage full</span>
                    </div>
                )}
            </div>
        );
    };

    return (
        <div className="flex flex-col h-screen bg-gray-900 text-gray-100">
            {/* --- HEADER --- */}
            <header className="bg-gray-800/95 backdrop-blur-sm border-b border-gray-700 px-6 py-3 flex-shrink-0">
                <div className="flex justify-between items-center">
                    <div className="flex items-center gap-4">
                        <h1 className="text-xl font-bold text-white">ACE Pipeline</h1>
                        <div className="text-sm text-gray-400">
                            {user?.name && `Welcome, ${user.name}`}
                        </div>
                    </div>
                    <div className="flex items-center gap-4">
                        <StorageInfoComponent />
                        <button
                            onClick={() => logout()}
                            className="bg-red-600 hover:bg-red-700 text-white px-3 py-1.5 rounded text-sm font-medium transition-colors"
                        >
                            Sign Out
                        </button>
                    </div>
                </div>
            </header>

            {/* --- MAIN LAYOUT --- */}
            <div className="flex flex-1 overflow-hidden">
                {/* --- SIDEBAR --- */}
                <aside className="w-80 bg-gray-800/50 p-4 flex flex-col flex-shrink-0 border-r border-gray-700 overflow-hidden">
                    <button
                        onClick={handleStartNewJob}
                        className={`w-full flex items-center gap-3 p-3 rounded-lg text-left font-semibold mb-4 transition-colors min-w-0 ${getActiveJobId() === jobId && view.type === 'new_job' ? 'bg-blue-600 text-white' : 'bg-gray-700 hover:bg-gray-600 text-gray-200'}`}
                    >
                        <PlusIcon className="w-6 h-6 flex-shrink-0"/>
                        <span className="truncate">New Job</span>
                    </button>
                    <h2 className="px-2 text-sm font-semibold text-gray-400 uppercase tracking-wider mb-2">History</h2>
                    <div className="flex-grow overflow-y-auto overflow-x-hidden pr-1">
                        {history.length === 0 ? (
                            <div className="text-center text-gray-500 p-4">No jobs completed yet.</div>
                        ) : (
                            <ul className="space-y-1">
                                {history
                                    .filter((h, index, arr) => arr.findIndex(item => item.id === h.id) === index) // Remove any runtime duplicates
                                    .map(h => (
                                    <li key={h.id} className="group">
                                        <div className="flex items-center min-w-0">
                                            <button 
                                                onClick={() => setView({ type: 'view_history', jobId: h.id })} 
                                                className={`flex-1 min-w-0 text-left p-3 rounded-l-lg transition-colors ${getActiveJobId() === h.id ? 'bg-gray-700' : 'hover:bg-gray-700/50'}`}
                                            >
                                                <div className="flex items-start gap-3 min-w-0">
                                                    <DocumentTextIcon className="w-6 h-6 text-gray-400 mt-0.5 flex-shrink-0"/>
                                                    <div className="flex-1 min-w-0">
                                                        <p className="font-medium text-gray-200 truncate" title={h.filename}>{h.filename}</p>
                                                        <p className="text-xs text-gray-400 truncate">{new Date(h.date).toLocaleDateString()}</p>
                                                        <div className="text-xs mt-1">
                                                            <span className="text-green-400">{h.completedCount}</span>
                                                            <span className="text-gray-500"> / </span>
                                                            <span className="text-red-400">{h.failedCount}</span>
                                                            {h.results && h.results.length > 0 && (
                                                                <span className="text-blue-400 ml-2">• Full Results</span>
                                                            )}
                                                        </div>
                                                    </div>
                                                </div>
                                            </button>
                                            <button
                                                onClick={(e) => {
                                                    e.stopPropagation();
                                                    setDeleteConfirmId(h.id);
                                                }}
                                                className="p-3 text-gray-500 hover:text-red-400 hover:bg-red-900/20 rounded-r-lg transition-colors opacity-0 group-hover:opacity-100 flex-shrink-0"
                                                title="Delete job"
                                            >
                                                <TrashIcon className="w-4 h-4" />
                                            </button>
                                        </div>
                                    </li>
                                ))}
                            </ul>
                        )}
                    </div>
                </aside>
                
                {/* --- MAIN CONTENT --- */}
                <main className="flex-grow p-8 flex items-center justify-center overflow-auto">
                    {error && view.type === 'new_job' && (
                        <div className="fixed top-20 right-4 max-w-sm text-left text-red-200 bg-red-900/70 p-4 rounded-lg shadow-lg border border-red-700 z-50">
                            <div className="flex items-start justify-between gap-3">
                                <div>
                                    <div className="font-semibold">Issues detected during processing</div>
                                    <div className="text-sm mt-1">{error}</div>
                                    {errors.length > 0 && (
                                        <button 
                                            className="mt-3 text-xs underline text-red-200 hover:text-white"
                                            onClick={() => setShowErrorDetails(true)}
                                        >
                                            View details ({errors.length})
                                        </button>
                                    )}
                                </div>
                                <button
                                    onClick={() => { setError(null); }}
                                    className="text-xs px-2 py-1 bg-red-800 hover:bg-red-700 rounded text-red-100"
                                    title="Dismiss"
                                >Dismiss</button>
                            </div>
                        </div>
                    )}
                    {renderMainContent()}
                </main>
            </div>
            
            {/* --- DELETE CONFIRMATION DIALOG --- */}
            {deleteConfirmId && (
                <DeleteConfirmationDialog
                    jobId={deleteConfirmId}
                    filename={history.find(h => h.id === deleteConfirmId)?.filename || 'Unknown'}
                    onConfirm={() => handleDeleteJob(deleteConfirmId)}
                    onCancel={() => setDeleteConfirmId(null)}
                />
            )}

            {/* --- ERROR DETAILS MODAL --- */}
            {showErrorDetails && <ErrorDetailsModal onClose={() => setShowErrorDetails(false)} items={errors} />}
        </div>
    );
};

// Simple router to handle signin vs main app
const AppRouter: React.FC = () => {
    const [currentPath, setCurrentPath] = useState(window.location.pathname);
    
    useEffect(() => {
        const handlePopState = () => {
            setCurrentPath(window.location.pathname);
        };
        
        window.addEventListener('popstate', handlePopState);
        return () => window.removeEventListener('popstate', handlePopState);
    }, []);

    // Route to signin page
    if (currentPath === '/auth/signin' || currentPath.startsWith('/auth/signin')) {
        return <SignInPage />;
    }
    
    // Default to main authenticated app
    return <AuthenticatedApp />;
};

// Main App component wrapped with authentication
const AuthenticatedApp: React.FC = () => {
    const { user, isAuthenticated, isLoading, logout } = useAuth();

    if (isLoading) {
        return (
            <div className="min-h-screen flex items-center justify-center bg-gray-900">
                <Spinner />
            </div>
        );
    }

    if (!isAuthenticated || !user) {
        // Show signin page instead of redirecting
        return <SignInPage />;
    }

    return <App />;
};

// Root component with routing
const AppWithAuth: React.FC = () => {
    return <AppRouter />;
};

export default AppWithAuth;