import React, { useEffect, useMemo, useState, useRef } from 'react';
import { 
  ThemeProvider, 
  createTheme, 
  useMediaQuery, 
  Button, 
  List, 
  ListItem, 
  ListItemText, 
  IconButton, 
  styled, 
  CircularProgress, 
  Divider, 
  Menu, 
  MenuItem,
  Box,
  Typography,
  LinearProgress,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  Chip,
  Tooltip,
  Alert
} from '@mui/material';
import UploadIcon from '@mui/icons-material/Upload';
import FolderIcon from '@mui/icons-material/Folder';
import FolderOpenIcon from '@mui/icons-material/FolderOpen';
import DeleteIcon from '@mui/icons-material/Delete';
import RefreshIcon from '@mui/icons-material/Refresh';
import MoreVertIcon from '@mui/icons-material/MoreVert';
import ImageIcon from '@mui/icons-material/Image';
import DescriptionIcon from '@mui/icons-material/Description';
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
import { useTLDraw } from '../../../../../contexts/TLDrawContext';
import { useAuth } from '../../../../../contexts/AuthContext';
import { useNavigate } from 'react-router-dom';
import { 
  pickDirectory, 
  processDirectoryFiles, 
  calculateDirectoryStats, 
  createDirectoryTree, 
  formatFileSize,
  isDirectoryPickerSupported,
  FileWithPath
} from '../../../../folderPicker';
import pLimit from 'p-limit';

const Container = styled('div')(() => ({
  padding: '8px',
  display: 'flex',
  flexDirection: 'column',
  gap: '8px',
  height: '100%'
}));

const Row = styled('div')(() => ({
  display: 'flex',
  gap: '8px',
  alignItems: 'center'
}));

type Cabinet = { id: string; name: string };
type FileRow = { id: string; name: string; mime_type?: string; is_directory?: boolean; size_bytes?: number };
type Artefact = { id: string; type: string; rel_path: string; created_at: string };

interface UploadProgress {
  path: string;
  size: number;
  status: 'queued' | 'uploading' | 'done' | 'error';
  progress: number;
  error?: string;
}

export const CCFilesPanelEnhanced: React.FC = () => {
  const { tldrawPreferences } = useTLDraw() as { tldrawPreferences?: { colorScheme?: 'light' | 'dark' | 'system' } };
  const { user: authUser, accessToken } = useAuth();
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
  const [cabinets, setCabinets] = useState<Cabinet[]>([]);
  const [selectedCabinet, setSelectedCabinet] = useState<string>('');
  const [files, setFiles] = useState<FileRow[]>([]);
  const [loading, setLoading] = useState(false);
  const [menuAnchor, setMenuAnchor] = useState<null | { el: HTMLElement; fileId: string }>(null);
  const [artefacts, setArtefacts] = useState<Artefact[]>([]);
  
  // Directory upload states
  const [uploadProgress, setUploadProgress] = useState<UploadProgress[]>([]);
  const [showUploadDialog, setShowUploadDialog] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [selectedFiles, setSelectedFiles] = useState<FileWithPath[]>([]);
  const [directoryStats, setDirectoryStats] = useState<any>(null);
  
  const navigate = useNavigate();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const dirInputRef = useRef<HTMLInputElement>(null);

  const theme = useMemo(() => {
    const mode = (tldrawPreferences?.colorScheme === 'system')
      ? (prefersDarkMode ? 'dark' : 'light')
      : (tldrawPreferences?.colorScheme === 'dark' ? 'dark' : 'light');
    return createTheme({ palette: { mode, divider: 'var(--color-divider)' } });
  }, [tldrawPreferences?.colorScheme, prefersDarkMode]);

  type RequestInitLike = { method?: string; body?: FormData | string | Blob | null; headers?: Record<string, string> } | undefined;
  type HeadersInitLike = Record<string, string>;

  const API_BASE: string = (import.meta as unknown as { env?: { VITE_API_BASE?: string } })?.env?.VITE_API_BASE || (location.port.startsWith('517') ? 'http://127.0.0.1:8080' : '/api');

  const apiFetch = async (url: string, init?: RequestInitLike) => {
    const headers: HeadersInitLike = {
      'Authorization': `Bearer ${accessToken || ''}`,
      ...(init?.headers || {})
    };
    const fullUrl = url.startsWith('http') ? url : `${API_BASE}${url}`;
    const res = await fetch(fullUrl, { ...(init || {}), headers });
    if (!res.ok) throw new Error(await res.text());
    return res.json();
  };

  const loadCabinets = async () => {
    setLoading(true);
    try {
      const data = await apiFetch('/database/cabinets');
      const all = [...(data.owned || []), ...(data.shared || [])];
      setCabinets(all);
      if (all.length && !selectedCabinet) setSelectedCabinet(all[0].id);
    } finally {
      setLoading(false);
    }
  };

  const loadFiles = async (cabinetId: string) => {
    setLoading(true);
    try {
      const data = await apiFetch(`/simple-upload/files?cabinet_id=${encodeURIComponent(cabinetId)}`);
      setFiles(data.files || []);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { if (authUser?.id) { loadCabinets(); } }, [authUser?.id]);
  useEffect(() => { if (selectedCabinet) loadFiles(selectedCabinet); }, [selectedCabinet]);

  const handleSingleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files || !selectedCabinet) return;
    const file = e.target.files[0];
    const form = new FormData();
    form.append('cabinet_id', selectedCabinet);
    form.append('path', file.name);
    form.append('scope', 'teacher');
    form.append('file', file);
    
    try {
      await apiFetch('/simple-upload/files/upload', { method: 'POST', body: form });
      await loadFiles(selectedCabinet);
      (e.target as HTMLInputElement).value = '';
    } catch (error) {
      console.error('Upload failed:', error);
      alert(`Upload failed: ${error}`);
    }
  };

  const handleDirectoryPicker = async () => {
    try {
      const files = await pickDirectory();
      prepareDirectoryUpload(files);
    } catch (error: any) {
      if (error.message === 'fallback-input') {
        // Use fallback input
        dirInputRef.current?.click();
      } else if (error.message === 'user-cancelled') {
        // User cancelled, do nothing
      } else {
        console.error('Directory picker error:', error);
        alert('Failed to pick directory. Please try the fallback method.');
        dirInputRef.current?.click();
      }
    }
  };

  const handleFallbackDirectorySelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) return;
    const files = processDirectoryFiles(e.target.files);
    prepareDirectoryUpload(files);
    e.target.value = ''; // Reset input
  };

  const prepareDirectoryUpload = (files: FileWithPath[]) => {
    if (files.length === 0) {
      alert('No files selected');
      return;
    }

    setSelectedFiles(files);
    setDirectoryStats(calculateDirectoryStats(files));
    
    // Initialize upload progress
    const progress: UploadProgress[] = files.map(file => ({
      path: file.relativePath,
      size: file.size,
      status: 'queued',
      progress: 0
    }));
    setUploadProgress(progress);
    setShowUploadDialog(true);
  };

  const startDirectoryUpload = async () => {
    if (!selectedCabinet || selectedFiles.length === 0) return;

    setIsUploading(true);
    
    try {
      // Get directory name from first file's path
      const firstFilePath = selectedFiles[0].relativePath;
      const directoryName = firstFilePath.split('/')[0] || 'uploaded-folder';
      
      // Prepare form data
      const formData = new FormData();
      formData.append('cabinet_id', selectedCabinet);
      formData.append('scope', 'teacher');
      formData.append('directory_name', directoryName);
      
      // Add all files
      selectedFiles.forEach(file => {
        formData.append('files', file);
      });
      
      // Add relative paths as JSON
      const relativePaths = selectedFiles.map(f => f.relativePath);
      formData.append('file_paths', JSON.stringify(relativePaths));
      
      // Upload directory
      const result = await apiFetch('/simple-upload/files/upload-directory', { 
        method: 'POST', 
        body: formData 
      });
      
      console.log('Directory upload result:', result);
      
      // Update progress to completed
      setUploadProgress(prev => prev.map(item => ({
        ...item,
        status: 'done',
        progress: 100
      })));
      
      // Refresh file list
      await loadFiles(selectedCabinet);
      
      // Close dialog after a short delay
      setTimeout(() => {
        setShowUploadDialog(false);
        setIsUploading(false);
        setSelectedFiles([]);
        setUploadProgress([]);
      }, 2000);
      
    } catch (error) {
      console.error('Directory upload failed:', error);
      alert(`Directory upload failed: ${error}`);
      
      // Mark all as error
      setUploadProgress(prev => prev.map(item => ({
        ...item,
        status: 'error',
        error: String(error)
      })));
      
      setIsUploading(false);
    }
  };

  const handleDelete = async (fileId: string) => {
    try {
      await apiFetch(`/simple-upload/files/${fileId}`, { method: 'DELETE' });
      await loadFiles(selectedCabinet);
    } catch (error) {
      console.error('Delete failed:', error);
      alert(`Delete failed: ${error}`);
    }
  };

  const handleGenerateInitial = async (fileId: string) => {
    // This would trigger manual processing if we implement it later
    alert('Manual processing not yet implemented');
  };

  const openMenu = (el: HTMLElement, fileId: string) => setMenuAnchor({ el, fileId });
  const closeMenu = () => setMenuAnchor(null);
  
  const goToAIContent = () => {
    if (!menuAnchor) return;
    const fileId = menuAnchor.fileId;
    closeMenu();
    navigate(`/doc-intelligence/${encodeURIComponent(fileId)}`);
  };

  const iconForMime = (mime?: string, isDirectory?: boolean) => {
    if (isDirectory) return <FolderIcon />;
    if (!mime) return <InsertDriveFileIcon />;
    if (mime.startsWith('image/')) return <ImageIcon />;
    if (mime === 'application/pdf' || mime.startsWith('application/')) return <DescriptionIcon />;
    return <InsertDriveFileIcon />;
  };

  const formatFileInfo = (file: FileRow) => {
    if (file.is_directory) {
      return `Directory • ${file.size_bytes ? formatFileSize(file.size_bytes) : 'Unknown size'}`;
    }
    return file.size_bytes ? formatFileSize(file.size_bytes) : 'Unknown size';
  };

  return (
    <ThemeProvider theme={theme}>
      <Container>
        <Row>
          <Button size="small" startIcon={<RefreshIcon/>} onClick={loadCabinets}>Refresh</Button>
        </Row>
        
        <List dense sx={{ border: '1px solid var(--color-divider)', borderRadius: '4px', overflow: 'auto', maxHeight: 140 }}>
          {cabinets.map(c => (
            <ListItem key={c.id} selected={c.id === selectedCabinet} onClick={() => setSelectedCabinet(c.id)} sx={{ cursor: 'pointer' }}>
              <FolderIcon sx={{ mr: 1 }}/>
              <ListItemText primary={c.name} secondary={c.id} />
            </ListItem>
          ))}
        </List>

        <Divider/>

        <Row>
          {/* Single file upload */}
          <input id="cc-file-input" type="file" style={{ display: 'none' }} onChange={handleSingleUpload}/>
          <label htmlFor="cc-file-input">
            <Button size="small" variant="outlined" startIcon={<UploadIcon/>} component="span" disabled={!selectedCabinet}>
              Upload File
            </Button>
          </label>
          
          {/* Directory upload */}
          <input 
            ref={dirInputRef}
            type="file" 
            style={{ display: 'none' }} 
            webkitdirectory="" 
            multiple 
            onChange={handleFallbackDirectorySelect}
          />
          
          <Tooltip title={isDirectoryPickerSupported() ? "Uses modern directory picker" : "Uses fallback method"}>
            <Button 
              size="small" 
              variant="outlined" 
              startIcon={<FolderOpenIcon/>} 
              onClick={handleDirectoryPicker}
              disabled={!selectedCabinet}
            >
              Upload Folder
            </Button>
          </Tooltip>
        </Row>

        {loading ? <CircularProgress size={20}/> : (
          <List dense sx={{ border: '1px solid var(--color-divider)', borderRadius: '4px', overflow: 'auto', flex: 1 }}>
            {files.map(f => (
              <ListItem key={f.id}
                secondaryAction={
                  <>
                    <IconButton size="small" onClick={(e) => openMenu(e.currentTarget, f.id)} title="File actions">
                      <MoreVertIcon/>
                    </IconButton>
                    <IconButton edge="end" size="small" onClick={() => handleDelete(f.id)} title="Delete file">
                      <DeleteIcon/>
                    </IconButton>
                  </>
                }
              >
                {iconForMime(f.mime_type, f.is_directory)}
                <ListItemText 
                  sx={{ ml: 1 }} 
                  primary={f.name} 
                  secondary={formatFileInfo(f)}
                />
                {f.is_directory && <Chip label="Directory" size="small" />}
              </ListItem>
            ))}
          </List>
        )}

        <Menu
          anchorEl={menuAnchor?.el ?? null}
          open={!!menuAnchor}
          onClose={closeMenu}
          anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
          transformOrigin={{ vertical: 'top', horizontal: 'right' }}
        >
          <MenuItem onClick={() => { if (menuAnchor) { handleGenerateInitial(menuAnchor.fileId); closeMenu(); } }}>
            Process manually
          </MenuItem>
          <MenuItem onClick={goToAIContent}>Open AI content</MenuItem>
        </Menu>

        {/* Directory Upload Dialog */}
        <Dialog open={showUploadDialog} onClose={() => !isUploading && setShowUploadDialog(false)} maxWidth="md" fullWidth>
          <DialogTitle>
            <Box display="flex" alignItems="center" gap={1}>
              <CloudUploadIcon />
              Directory Upload
              {isUploading && <CircularProgress size={20} />}
            </Box>
          </DialogTitle>
          
          <DialogContent>
            {directoryStats && (
              <Box sx={{ mb: 2 }}>
                <Alert severity="info">
                  <Typography variant="body2">
                    <strong>{directoryStats.fileCount} files</strong> in{' '}
                    <strong>{directoryStats.directoryCount} folders</strong><br/>
                    Total size: <strong>{directoryStats.formattedSize}</strong>
                  </Typography>
                </Alert>
              </Box>
            )}
            
            <Box sx={{ mb: 2 }}>
              <Typography variant="h6" gutterBottom>
                Upload Progress
              </Typography>
              
              {uploadProgress.length > 0 && (
                <>
                  <Box sx={{ mb: 1 }}>
                    <Typography variant="body2" color="textSecondary">
                      {uploadProgress.filter(p => p.status === 'done').length} / {uploadProgress.length} files completed
                    </Typography>
                    <LinearProgress 
                      variant="determinate" 
                      value={(uploadProgress.filter(p => p.status === 'done').length / uploadProgress.length) * 100}
                      sx={{ mt: 1 }}
                    />
                  </Box>
                  
                  <Box sx={{ maxHeight: 300, overflow: 'auto', border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
                    <table style={{ width: '100%', fontSize: '0.875rem' }}>
                      <thead>
                        <tr style={{ borderBottom: '1px solid', backgroundColor: 'rgba(0,0,0,0.05)' }}>
                          <th style={{ textAlign: 'left', padding: '8px' }}>Path</th>
                          <th style={{ textAlign: 'right', padding: '8px' }}>Size</th>
                          <th style={{ textAlign: 'center', padding: '8px' }}>Status</th>
                        </tr>
                      </thead>
                      <tbody>
                        {uploadProgress.map((item, i) => (
                          <tr key={i} style={{ borderBottom: '1px solid rgba(0,0,0,0.1)' }}>
                            <td style={{ padding: '4px 8px', maxWidth: 300, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                              {item.path}
                            </td>
                            <td style={{ padding: '4px 8px', textAlign: 'right' }}>
                              {formatFileSize(item.size)}
                            </td>
                            <td style={{ padding: '4px 8px', textAlign: 'center' }}>
                              <Chip 
                                label={item.status}
                                size="small"
                                color={
                                  item.status === 'done' ? 'success' : 
                                  item.status === 'error' ? 'error' : 
                                  item.status === 'uploading' ? 'primary' : 'default'
                                }
                              />
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </Box>
                </>
              )}
            </Box>
          </DialogContent>
          
          <DialogActions>
            <Button onClick={() => setShowUploadDialog(false)} disabled={isUploading}>
              Cancel
            </Button>
            <Button 
              onClick={startDirectoryUpload} 
              variant="contained" 
              disabled={isUploading || selectedFiles.length === 0}
              startIcon={isUploading ? <CircularProgress size={16} /> : <CloudUploadIcon />}
            >
              {isUploading ? 'Uploading...' : 'Start Upload'}
            </Button>
          </DialogActions>
        </Dialog>
      </Container>
    </ThemeProvider>
  );
};

export default CCFilesPanelEnhanced;
