import { useState, useEffect, useRef } from 'react';
import { exchangeDropboxCode, getDropboxFolder } from '../api/client';

const DROPBOX_APP_KEY = import.meta.env.VITE_DROPBOX_APP_KEY;
const REDIRECT_URI = window.location.origin;

// Supported file extensions (Docling supports many formats)
const SUPPORTED_EXTENSIONS = ['.txt', '.md', '.pdf', '.docx', '.pptx', '.xlsx', '.html', '.htm', '.jpg', '.jpeg', '.png', '.bmp', '.tiff'];
const MAX_FILE_SIZE_MB = 10;
const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;

export default function CloudConnect({ onFilesStaged, stagedFiles = [], onAccessTokenChange }) {
  const [isSignedIn, setIsSignedIn] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  const [accessToken, setAccessToken] = useState(null);
  const [showPicker, setShowPicker] = useState(false);
  const [files, setFiles] = useState([]);
  const [folders, setFolders] = useState([]);
  const [currentPath, setCurrentPath] = useState('');
  const [pathStack, setPathStack] = useState([]);
  const [pickerSelectedFiles, setPickerSelectedFiles] = useState([]);
  const [loadingFiles, setLoadingFiles] = useState(false);

  const popupRef = useRef(null);
  const popupCheckInterval = useRef(null);

  // Listen for OAuth callback message from popup
  useEffect(() => {
    const handleMessage = async (event) => {
      // Verify origin for security
      if (event.origin !== window.location.origin) return;

      if (event.data?.type === 'DROPBOX_AUTH_CODE') {
        const { code, error: authError } = event.data;

        // Close popup
        if (popupRef.current && !popupRef.current.closed) {
          popupRef.current.close();
        }
        clearInterval(popupCheckInterval.current);

        if (authError) {
          setError(`Dropbox error: ${authError}`);
          setIsLoading(false);
          return;
        }

        if (code) {
          try {
            const data = await exchangeDropboxCode(code, REDIRECT_URI);
            if (data.access_token) {
              setAccessToken(data.access_token);
              setIsSignedIn(true);
              onAccessTokenChange?.(data.access_token);
            } else {
              setError(data.error || 'Failed to get access token');
            }
          } catch (err) {
            setError(err.message);
          }
          setIsLoading(false);
        }
      }
    };

    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [onAccessTokenChange]);

  // Check if this is the OAuth callback page (popup)
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const code = params.get('code');
    const errorParam = params.get('error');

    // If we have code/error and we're in a popup, send message to parent
    if ((code || errorParam) && window.opener) {
      window.opener.postMessage({
        type: 'DROPBOX_AUTH_CODE',
        code: code,
        error: errorParam
      }, window.location.origin);
      window.close();
    }
  }, []);

  // Fetch folder contents
  const fetchFolder = async (path) => {
    setLoadingFiles(true);
    setError(null);
    try {
      const data = await getDropboxFolder(path, accessToken);

      if (data.error) {
        setError(data.error);
        setLoadingFiles(false);
        return;
      }

      const entries = data.entries || [];
      const folderItems = entries.filter(item => item['.tag'] === 'folder');
      const fileItems = entries.filter(item => item['.tag'] === 'file');

      setFolders(folderItems);
      setFiles(fileItems);
    } catch (err) {
      setError(`Failed to load files: ${err.message}`);
    }
    setLoadingFiles(false);
  };

  // Check if file is supported
  const isFileSupported = (file) => {
    const name = file.name.toLowerCase();
    return SUPPORTED_EXTENSIONS.some(ext => name.endsWith(ext));
  };

  // Check if file size is within limit
  const isFileSizeOk = (file) => {
    return file.size <= MAX_FILE_SIZE_BYTES;
  };

  // Open picker
  const openPicker = () => {
    setShowPicker(true);
    setPickerSelectedFiles([]);
    setCurrentPath('');
    setPathStack([]);
    fetchFolder('');
  };

  // Navigate to folder
  const navigateToFolder = (folder) => {
    setPathStack([...pathStack, { path: currentPath, name: currentPath || 'Dropbox' }]);
    setCurrentPath(folder.path_lower);
    fetchFolder(folder.path_lower);
  };

  // Go back
  const goBack = () => {
    if (pathStack.length > 0) {
      const prev = pathStack[pathStack.length - 1];
      setPathStack(pathStack.slice(0, -1));
      setCurrentPath(prev.path);
      fetchFolder(prev.path);
    }
  };

  // Toggle file selection in picker
  const toggleFile = (file) => {
    if (!isFileSupported(file)) return;
    if (!isFileSizeOk(file)) return;

    if (pickerSelectedFiles.find(f => f.id === file.id)) {
      setPickerSelectedFiles(pickerSelectedFiles.filter(f => f.id !== file.id));
    } else {
      setPickerSelectedFiles([...pickerSelectedFiles, file]);
    }
  };

  // Confirm selection - adds to staged files
  const confirmSelection = () => {
    // Merge with existing staged files, avoiding duplicates
    const existingIds = new Set(stagedFiles.map(f => f.id));
    const newFiles = pickerSelectedFiles.filter(f => !existingIds.has(f.id));
    const merged = [...stagedFiles, ...newFiles];
    onFilesStaged?.(merged);
    setShowPicker(false);
  };

  const handleConnect = () => {
    if (!DROPBOX_APP_KEY) {
      setError('Dropbox App Key not configured');
      return;
    }

    setIsLoading(true);
    setError(null);

    const authUrl = new URL('https://www.dropbox.com/oauth2/authorize');
    authUrl.searchParams.set('client_id', DROPBOX_APP_KEY);
    authUrl.searchParams.set('response_type', 'code');
    authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
    authUrl.searchParams.set('token_access_type', 'offline');

    // Open popup window for OAuth
    const width = 500;
    const height = 700;
    const left = window.screenX + (window.outerWidth - width) / 2;
    const top = window.screenY + (window.outerHeight - height) / 2;

    popupRef.current = window.open(
      authUrl.toString(),
      'dropbox-auth',
      `width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no,scrollbars=yes`
    );

    // Check if popup was blocked
    if (!popupRef.current || popupRef.current.closed) {
      setError('Popup blocked. Please allow popups for this site.');
      setIsLoading(false);
      return;
    }

    // Monitor popup - if user closes it manually
    popupCheckInterval.current = setInterval(() => {
      if (popupRef.current && popupRef.current.closed) {
        clearInterval(popupCheckInterval.current);
        setIsLoading(false);
      }
    }, 500);
  };

  const handleDisconnect = () => {
    setAccessToken(null);
    setIsSignedIn(false);
    setShowPicker(false);
    onAccessTokenChange?.(null);
    onFilesStaged?.([]);
  };

  // Get display name for current path
  const getCurrentFolderName = () => {
    if (!currentPath) return 'Dropbox';
    const parts = currentPath.split('/');
    return parts[parts.length - 1] || 'Dropbox';
  };

  // Format file size
  const formatSize = (bytes) => {
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  };

  if (!DROPBOX_APP_KEY) {
    return (
      <div className="bg-yellow-900/30 border border-yellow-700 rounded-lg p-3 text-sm text-yellow-400" role="alert">
        <p className="font-medium">Dropbox not configured</p>
        <p className="text-xs mt-1 text-yellow-500">Set VITE_DROPBOX_APP_KEY in environment</p>
      </div>
    );
  }

  return (
    <div className="space-y-3">
      {error && (
        <div className="bg-red-900/30 border border-red-700 rounded-lg p-3 text-sm text-red-400" role="alert">
          {error}
        </div>
      )}

      {!isSignedIn ? (
        <div className="space-y-3">
          <button
            type="button"
            onClick={handleConnect}
            disabled={isLoading}
            className="w-full flex items-center justify-center gap-2 bg-slate-700 border border-slate-600 rounded-lg px-4 py-2.5 text-sm font-medium text-slate-200 hover:bg-slate-600 active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed shadow-sm transition-all duration-200"
          >
            {isLoading ? (
              <div className="w-5 h-5 border-2 border-slate-400 border-t-transparent rounded-full animate-spin"></div>
            ) : (
              <svg className="w-5 h-5" viewBox="0 0 24 24" fill="#0061FF">
                <path d="M12 6.5l-6 3.75L12 14l6-3.75L12 6.5zM6 14l6 3.75L18 14l-6 3.75L6 14zM6 10.25L0 6.5l6-3.75 6 3.75-6 3.75zM18 10.25l6-3.75-6-3.75-6 3.75 6 3.75z"/>
              </svg>
            )}
            Connect Dropbox
          </button>
          <p className="text-xs text-slate-500 text-center">
            PDF, DOCX, PPTX, XLSX, HTML, images (max {MAX_FILE_SIZE_MB} MB)
          </p>
        </div>
      ) : (
        <div className="space-y-3">
          {/* Connection status */}
          <div className="flex items-center justify-between text-sm bg-green-900/30 border border-green-700 rounded-lg px-3 py-2">
            <div className="flex items-center gap-2 text-green-400">
              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
              </svg>
              <span>Connected to Dropbox</span>
            </div>
            <button
              type="button"
              onClick={handleDisconnect}
              className="text-xs text-green-400 hover:text-green-300 font-medium"
              aria-label="Disconnect from Dropbox"
            >
              Disconnect
            </button>
          </div>

          {/* Select files button */}
          <button
            type="button"
            onClick={openPicker}
            className="w-full flex items-center justify-center gap-2 bg-slate-700 border border-slate-600 text-slate-200 rounded-lg px-4 py-2.5 text-sm font-medium hover:bg-slate-600 active:scale-[0.98] shadow-sm transition-all duration-200"
          >
            <svg className="w-5 h-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
            </svg>
            {stagedFiles.length > 0 ? 'Add More Files' : 'Select Files'}
          </button>

          {/* File type hints */}
          <p className="text-xs text-slate-500 text-center">
            PDF, DOCX, PPTX, XLSX, HTML, images (max {MAX_FILE_SIZE_MB} MB)
          </p>
        </div>
      )}

      {/* File Picker Modal */}
      {showPicker && (
        <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
          <div className="bg-slate-800 border border-slate-700 rounded-xl w-full max-w-2xl max-h-[80vh] flex flex-col shadow-xl">
            {/* Header */}
            <div className="p-4 border-b border-slate-700 flex items-center justify-between">
              <div className="flex items-center gap-2">
                {pathStack.length > 0 && (
                  <button
                    type="button"
                    onClick={goBack}
                    className="p-1.5 hover:bg-slate-700 rounded-lg transition-colors"
                    aria-label="Go back"
                  >
                    <svg className="w-5 h-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                    </svg>
                  </button>
                )}
                <h3 className="font-medium text-slate-100">{getCurrentFolderName()}</h3>
              </div>
              <button
                type="button"
                onClick={() => setShowPicker(false)}
                className="p-1.5 hover:bg-slate-700 rounded-lg transition-colors"
                aria-label="Close picker"
              >
                <svg className="w-5 h-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            </div>

            {/* File list */}
            <div className="flex-1 overflow-auto p-3">
              {loadingFiles ? (
                <div className="flex items-center justify-center py-12">
                  <div className="w-6 h-6 border-2 border-blue-400 border-t-transparent rounded-full animate-spin"></div>
                </div>
              ) : (
                <div className="space-y-1">
                  {folders.map(folder => (
                    <div
                      key={folder.id}
                      onClick={() => navigateToFolder(folder)}
                      className="flex items-center gap-3 p-2.5 hover:bg-slate-700 rounded-lg cursor-pointer transition-colors"
                    >
                      <svg className="w-5 h-5 text-blue-400" fill="currentColor" viewBox="0 0 24 24">
                        <path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>
                      </svg>
                      <span className="text-sm text-slate-200">{folder.name}</span>
                    </div>
                  ))}
                  {files.map(file => {
                    const supported = isFileSupported(file);
                    const sizeOk = isFileSizeOk(file);
                    const selectable = supported && sizeOk;
                    const isSelected = pickerSelectedFiles.find(f => f.id === file.id);

                    return (
                      <div
                        key={file.id}
                        onClick={() => selectable && toggleFile(file)}
                        className={`flex items-center gap-3 p-2.5 rounded-lg transition-colors ${
                          !selectable
                            ? 'opacity-50 cursor-not-allowed'
                            : isSelected
                            ? 'bg-blue-900/40 border border-blue-700 cursor-pointer'
                            : 'hover:bg-slate-700 cursor-pointer'
                        }`}
                      >
                        <input
                          type="checkbox"
                          checked={!!isSelected}
                          disabled={!selectable}
                          onChange={() => {}}
                          className="w-4 h-4 rounded border-slate-600 bg-slate-700 text-blue-500 focus:ring-blue-500"
                        />
                        <svg className="w-5 h-5 text-slate-500" fill="currentColor" viewBox="0 0 24 24">
                          <path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm-1 2l5 5h-5V4z"/>
                        </svg>
                        <div className="flex-1 min-w-0">
                          <span className="text-sm text-slate-200 truncate block">{file.name}</span>
                          <span className="text-xs text-slate-500">
                            {formatSize(file.size)}
                            {!supported && ' - Unsupported format'}
                            {supported && !sizeOk && ' - File too large'}
                          </span>
                        </div>
                      </div>
                    );
                  })}
                  {folders.length === 0 && files.length === 0 && (
                    <div className="text-center py-12">
                      <svg className="w-12 h-12 text-slate-600 mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
                      </svg>
                      <p className="text-slate-500 text-sm">This folder is empty</p>
                    </div>
                  )}
                </div>
              )}
            </div>

            {/* Footer */}
            <div className="p-4 border-t border-slate-700 flex items-center justify-between bg-slate-800/50 rounded-b-xl">
              <span className="text-sm text-slate-400">
                {pickerSelectedFiles.length} file(s) selected
              </span>
              <div className="flex gap-2">
                <button
                  type="button"
                  onClick={() => setShowPicker(false)}
                  className="px-4 py-2 text-sm font-medium text-slate-300 hover:bg-slate-700 rounded-lg transition-colors"
                >
                  Cancel
                </button>
                <button
                  type="button"
                  onClick={confirmSelection}
                  disabled={pickerSelectedFiles.length === 0}
                  className="px-4 py-2 text-sm font-medium bg-blue-600 text-white rounded-lg hover:bg-blue-700 active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200"
                >
                  Add Selected
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
