/**
 * Atomizer Studio - Unified Study Creation Environment
 * 
 * A drag-and-drop workspace for creating optimization studies with:
 * - File upload (models + context documents)
 * - Visual canvas configuration
 * - AI-powered assistance
 * - One-click build to final study
 */

import { useState, useEffect, useCallback, useRef } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import {
  Home,
  ChevronRight,
  Upload,
  FileText,
  Settings,
  Sparkles,
  Save,
  RefreshCw,
  Trash2,
  MessageSquare,
  Layers,
  CheckCircle,
  AlertCircle,
  Loader2,
  X,
  ChevronLeft,
  ChevronRight as ChevronRightIcon,
  GripVertical,
} from 'lucide-react';
import { intakeApi } from '../api/intake';
import { SpecRenderer } from '../components/canvas/SpecRenderer';
import { NodePalette } from '../components/canvas/palette/NodePalette';
import { NodeConfigPanelV2 } from '../components/canvas/panels/NodeConfigPanelV2';
import { useSpecStore, useSpec, useSpecLoading } from '../hooks/useSpecStore';
import { StudioDropZone } from '../components/studio/StudioDropZone';
import { StudioParameterList } from '../components/studio/StudioParameterList';
import { StudioContextFiles } from '../components/studio/StudioContextFiles';
import { StudioChat } from '../components/studio/StudioChat';
import { StudioBuildDialog } from '../components/studio/StudioBuildDialog';

interface DraftState {
  draftId: string | null;
  status: 'idle' | 'creating' | 'ready' | 'error';
  error: string | null;
  modelFiles: string[];
  contextFiles: string[];
  contextContent: string;
  introspectionAvailable: boolean;
  designVariableCount: number;
  objectiveCount: number;
}

export default function Studio() {
  const navigate = useNavigate();
  const { draftId: urlDraftId } = useParams<{ draftId: string }>();
  
  // Draft state
  const [draft, setDraft] = useState<DraftState>({
    draftId: null,
    status: 'idle',
    error: null,
    modelFiles: [],
    contextFiles: [],
    contextContent: '',
    introspectionAvailable: false,
    designVariableCount: 0,
    objectiveCount: 0,
  });
  
  // UI state
  const [leftPanelWidth, setLeftPanelWidth] = useState(320);
  const [rightPanelCollapsed, setRightPanelCollapsed] = useState(false);
  const [showBuildDialog, setShowBuildDialog] = useState(false);
  const [isIntrospecting, setIsIntrospecting] = useState(false);
  const [notification, setNotification] = useState<{ type: 'success' | 'error' | 'info'; message: string } | null>(null);
  
  // Resize state
  const isResizing = useRef(false);
  const minPanelWidth = 280;
  const maxPanelWidth = 500;
  
  // Spec store for canvas
  const spec = useSpec();
  const specLoading = useSpecLoading();
  const { loadSpec, clearSpec } = useSpecStore();
  
  // Handle panel resize
  const handleMouseDown = useCallback((e: React.MouseEvent) => {
    e.preventDefault();
    isResizing.current = true;
    document.body.style.cursor = 'col-resize';
    document.body.style.userSelect = 'none';
  }, []);
  
  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!isResizing.current) return;
      const newWidth = Math.min(maxPanelWidth, Math.max(minPanelWidth, e.clientX));
      setLeftPanelWidth(newWidth);
    };
    
    const handleMouseUp = () => {
      isResizing.current = false;
      document.body.style.cursor = '';
      document.body.style.userSelect = '';
    };
    
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    
    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, []);
  
  // Initialize or load draft on mount
  useEffect(() => {
    if (urlDraftId) {
      loadDraft(urlDraftId);
    } else {
      createNewDraft();
    }
    
    return () => {
      // Cleanup: clear spec when leaving Studio
      clearSpec();
    };
  }, [urlDraftId]);
  
  // Create a new draft
  const createNewDraft = async () => {
    setDraft(prev => ({ ...prev, status: 'creating', error: null }));
    
    try {
      const response = await intakeApi.createDraft();
      
      setDraft({
        draftId: response.draft_id,
        status: 'ready',
        error: null,
        modelFiles: [],
        contextFiles: [],
        contextContent: '',
        introspectionAvailable: false,
        designVariableCount: 0,
        objectiveCount: 0,
      });
      
      // Update URL without navigation
      window.history.replaceState(null, '', `/studio/${response.draft_id}`);
      
      // Load the empty spec for this draft
      await loadSpec(response.draft_id);
      
      showNotification('info', 'New studio session started. Drop your files to begin.');
    } catch (err) {
      setDraft(prev => ({
        ...prev,
        status: 'error',
        error: err instanceof Error ? err.message : 'Failed to create draft',
      }));
    }
  };
  
  // Load existing draft or study
  const loadDraft = async (studyId: string) => {
    setDraft(prev => ({ ...prev, status: 'creating', error: null }));
    
    // Check if this is a draft (in _inbox) or an existing study
    const isDraft = studyId.startsWith('draft_');
    
    if (isDraft) {
      // Load from intake API
      try {
        const response = await intakeApi.getStudioDraft(studyId);
        
        // Also load context content if there are context files
        let contextContent = '';
        if (response.context_files.length > 0) {
          try {
            const contextResponse = await intakeApi.getContextContent(studyId);
            contextContent = contextResponse.content;
          } catch {
            // Ignore context loading errors
          }
        }
        
        setDraft({
          draftId: response.draft_id,
          status: 'ready',
          error: null,
          modelFiles: response.model_files,
          contextFiles: response.context_files,
          contextContent,
          introspectionAvailable: response.introspection_available,
          designVariableCount: response.design_variable_count,
          objectiveCount: response.objective_count,
        });
        
        // Load the spec
        await loadSpec(studyId);
        
        showNotification('info', `Resuming draft: ${studyId}`);
      } catch (err) {
        // Draft doesn't exist, create new one
        createNewDraft();
      }
    } else {
      // Load existing study directly via spec store
      try {
        await loadSpec(studyId);
        
        // Get counts from loaded spec
        const loadedSpec = useSpecStore.getState().spec;
        
        setDraft({
          draftId: studyId,
          status: 'ready',
          error: null,
          modelFiles: [], // Existing studies don't track files separately
          contextFiles: [],
          contextContent: '',
          introspectionAvailable: true, // Assume introspection was done
          designVariableCount: loadedSpec?.design_variables?.length || 0,
          objectiveCount: loadedSpec?.objectives?.length || 0,
        });
        
        showNotification('info', `Editing study: ${studyId}`);
      } catch (err) {
        setDraft(prev => ({
          ...prev,
          status: 'error',
          error: err instanceof Error ? err.message : 'Failed to load study',
        }));
      }
    }
  };
  
  // Refresh draft data
  const refreshDraft = async () => {
    if (!draft.draftId) return;
    
    const isDraft = draft.draftId.startsWith('draft_');
    
    if (isDraft) {
      try {
        const response = await intakeApi.getStudioDraft(draft.draftId);
        
        // Also refresh context content
        let contextContent = draft.contextContent;
        if (response.context_files.length > 0) {
          try {
            const contextResponse = await intakeApi.getContextContent(draft.draftId);
            contextContent = contextResponse.content;
          } catch {
            // Keep existing content
          }
        }
        
        setDraft(prev => ({
          ...prev,
          modelFiles: response.model_files,
          contextFiles: response.context_files,
          contextContent,
          introspectionAvailable: response.introspection_available,
          designVariableCount: response.design_variable_count,
          objectiveCount: response.objective_count,
        }));
        
        // Reload spec
        await loadSpec(draft.draftId);
      } catch (err) {
        showNotification('error', 'Failed to refresh draft');
      }
    } else {
      // For existing studies, just reload the spec
      try {
        await loadSpec(draft.draftId);
        
        const loadedSpec = useSpecStore.getState().spec;
        setDraft(prev => ({
          ...prev,
          designVariableCount: loadedSpec?.design_variables?.length || 0,
          objectiveCount: loadedSpec?.objectives?.length || 0,
        }));
      } catch (err) {
        showNotification('error', 'Failed to refresh study');
      }
    }
  };
  
  // Run introspection
  const runIntrospection = async () => {
    if (!draft.draftId || draft.modelFiles.length === 0) {
      showNotification('error', 'Please upload model files first');
      return;
    }
    
    setIsIntrospecting(true);
    
    try {
      const response = await intakeApi.introspect({ study_name: draft.draftId });
      
      showNotification('success', `Found ${response.expressions_count} expressions (${response.candidates_count} candidates)`);
      
      // Refresh draft state
      await refreshDraft();
    } catch (err) {
      showNotification('error', err instanceof Error ? err.message : 'Introspection failed');
    } finally {
      setIsIntrospecting(false);
    }
  };
  
  // Handle file upload complete
  const handleUploadComplete = useCallback(() => {
    refreshDraft();
    showNotification('success', 'Files uploaded successfully');
  }, [draft.draftId]);
  
  // Handle build complete
  const handleBuildComplete = (finalPath: string, finalName: string) => {
    setShowBuildDialog(false);
    showNotification('success', `Study "${finalName}" created successfully!`);
    
    // Navigate to the new study
    setTimeout(() => {
      navigate(`/canvas/${finalPath.replace('studies/', '')}`);
    }, 1500);
  };
  
  // Reset draft
  const resetDraft = async () => {
    if (!draft.draftId) return;
    
    if (!confirm('Are you sure you want to reset? This will delete all uploaded files and configurations.')) {
      return;
    }
    
    try {
      await intakeApi.deleteInboxStudy(draft.draftId);
      await createNewDraft();
    } catch (err) {
      showNotification('error', 'Failed to reset draft');
    }
  };
  
  // Show notification
  const showNotification = (type: 'success' | 'error' | 'info', message: string) => {
    setNotification({ type, message });
    setTimeout(() => setNotification(null), 4000);
  };
  
  // Can always save/build - even empty studies can be saved for later
  const canBuild = draft.draftId !== null;
  
  // Loading state
  if (draft.status === 'creating') {
    return (
      <div className="min-h-screen bg-dark-900 flex items-center justify-center">
        <div className="text-center">
          <Loader2 className="w-12 h-12 text-primary-400 animate-spin mx-auto mb-4" />
          <p className="text-dark-300">Initializing Studio...</p>
        </div>
      </div>
    );
  }
  
  // Error state
  if (draft.status === 'error') {
    return (
      <div className="min-h-screen bg-dark-900 flex items-center justify-center">
        <div className="text-center max-w-md">
          <AlertCircle className="w-12 h-12 text-red-400 mx-auto mb-4" />
          <h2 className="text-xl font-semibold text-white mb-2">Failed to Initialize</h2>
          <p className="text-dark-400 mb-4">{draft.error}</p>
          <button
            onClick={createNewDraft}
            className="px-4 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-400 transition-colors"
          >
            Try Again
          </button>
        </div>
      </div>
    );
  }
  
  return (
    <div className="min-h-screen bg-dark-900 flex flex-col">
      {/* Header */}
      <header className="h-14 bg-dark-850 border-b border-dark-700 flex items-center justify-between px-4 flex-shrink-0">
        {/* Left: Navigation */}
        <div className="flex items-center gap-3">
          <button
            onClick={() => navigate('/')}
            className="p-2 hover:bg-dark-700 rounded-lg text-dark-400 hover:text-white transition-colors"
          >
            <Home className="w-5 h-5" />
          </button>
          <ChevronRight className="w-4 h-4 text-dark-600" />
          <div className="flex items-center gap-2">
            <Sparkles className="w-5 h-5 text-primary-400" />
            <span className="text-white font-medium">Atomizer Studio</span>
          </div>
          {draft.draftId && (
            <>
              <ChevronRight className="w-4 h-4 text-dark-600" />
              <span className="text-dark-400 text-sm font-mono">{draft.draftId}</span>
            </>
          )}
        </div>
        
        {/* Right: Actions */}
        <div className="flex items-center gap-2">
          <button
            onClick={resetDraft}
            className="flex items-center gap-2 px-3 py-1.5 text-sm text-dark-400 hover:text-white hover:bg-dark-700 rounded-lg transition-colors"
          >
            <Trash2 className="w-4 h-4" />
            Reset
          </button>
          <button
            onClick={() => setShowBuildDialog(true)}
            disabled={!canBuild}
            className="flex items-center gap-2 px-4 py-1.5 text-sm font-medium bg-primary-500 text-white rounded-lg hover:bg-primary-400 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            <Save className="w-4 h-4" />
            Save & Name Study
          </button>
        </div>
      </header>
      
      {/* Main Content */}
      <div className="flex-1 flex overflow-hidden">
        {/* Left Panel: Resources (Resizable) */}
        <div
          className="bg-dark-850 border-r border-dark-700 flex flex-col flex-shrink-0 relative"
          style={{ width: leftPanelWidth }}
        >
          <div className="flex-1 overflow-y-auto p-4 space-y-6">
            {/* Drop Zone */}
            <section>
              <h3 className="text-sm font-medium text-dark-300 mb-3 flex items-center gap-2">
                <Upload className="w-4 h-4" />
                Model Files
              </h3>
              {draft.draftId && (
                <StudioDropZone
                  draftId={draft.draftId}
                  type="model"
                  files={draft.modelFiles}
                  onUploadComplete={handleUploadComplete}
                />
              )}
            </section>
            
            {/* Introspection */}
            {draft.modelFiles.length > 0 && (
              <section>
                <div className="flex items-center justify-between mb-3">
                  <h3 className="text-sm font-medium text-dark-300 flex items-center gap-2">
                    <Settings className="w-4 h-4" />
                    Parameters
                  </h3>
                  <button
                    onClick={runIntrospection}
                    disabled={isIntrospecting}
                    className="flex items-center gap-1 px-2 py-1 text-xs text-primary-400 hover:bg-primary-400/10 rounded transition-colors disabled:opacity-50"
                  >
                    {isIntrospecting ? (
                      <Loader2 className="w-3 h-3 animate-spin" />
                    ) : (
                      <RefreshCw className="w-3 h-3" />
                    )}
                    {isIntrospecting ? 'Scanning...' : 'Scan'}
                  </button>
                </div>
                {draft.draftId && draft.introspectionAvailable && (
                  <StudioParameterList
                    draftId={draft.draftId}
                    onParameterAdded={refreshDraft}
                  />
                )}
                {!draft.introspectionAvailable && (
                  <p className="text-xs text-dark-500 italic">
                    Click "Scan" to discover parameters from your model.
                  </p>
                )}
              </section>
            )}
            
            {/* Context Files */}
            <section>
              <h3 className="text-sm font-medium text-dark-300 mb-3 flex items-center gap-2">
                <FileText className="w-4 h-4" />
                Context Documents
              </h3>
              {draft.draftId && (
                <StudioContextFiles
                  draftId={draft.draftId}
                  files={draft.contextFiles}
                  onUploadComplete={handleUploadComplete}
                />
              )}
              <p className="text-xs text-dark-500 mt-2">
                Upload requirements, goals, or specs. The AI will read these.
              </p>
              
              {/* Show context preview if loaded */}
              {draft.contextContent && (
                <div className="mt-3 p-2 bg-dark-700/50 rounded-lg border border-dark-600">
                  <p className="text-xs text-amber-400 mb-1 font-medium">Context Loaded:</p>
                  <p className="text-xs text-dark-400 line-clamp-3">
                    {draft.contextContent.substring(0, 200)}...
                  </p>
                </div>
              )}
            </section>
            
            {/* Node Palette - EXPANDED, not collapsed */}
            <section>
              <h3 className="text-sm font-medium text-dark-300 mb-3 flex items-center gap-2">
                <Layers className="w-4 h-4" />
                Components
              </h3>
              <NodePalette 
                collapsed={false} 
                showToggle={false}
                className="!w-full !border-0 !bg-transparent"
              />
            </section>
          </div>
          
          {/* Resize Handle */}
          <div
            className="absolute right-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-primary-500/50 transition-colors group"
            onMouseDown={handleMouseDown}
          >
            <div className="absolute right-0 top-1/2 -translate-y-1/2 w-4 h-8 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
              <GripVertical className="w-3 h-3 text-dark-400" />
            </div>
          </div>
        </div>
        
        {/* Center: Canvas */}
        <div className="flex-1 relative bg-dark-900">
          {draft.draftId && (
            <SpecRenderer
              studyId={draft.draftId}
              editable={true}
              showLoadingOverlay={false}
            />
          )}
          
          {/* Empty state */}
          {!specLoading && (!spec || Object.keys(spec).length === 0) && (
            <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
              <div className="text-center max-w-md p-8">
                <div className="w-20 h-20 rounded-full bg-dark-800 flex items-center justify-center mx-auto mb-6">
                  <Sparkles className="w-10 h-10 text-primary-400" />
                </div>
                <h2 className="text-2xl font-semibold text-white mb-3">
                  Welcome to Atomizer Studio
                </h2>
                <p className="text-dark-400 mb-6">
                  Drop your model files on the left, or drag components from the palette to start building your optimization study.
                </p>
                <div className="flex flex-col gap-2 text-sm text-dark-500">
                  <div className="flex items-center gap-2">
                    <CheckCircle className="w-4 h-4 text-green-400" />
                    <span>Upload .sim, .prt, .fem files</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <CheckCircle className="w-4 h-4 text-green-400" />
                    <span>Add context documents (PDF, MD, TXT)</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <CheckCircle className="w-4 h-4 text-green-400" />
                    <span>Configure with AI assistance</span>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
        
        {/* Right Panel: Assistant + Config - wider for better chat UX */}
        <div
          className={`bg-dark-850 border-l border-dark-700 flex flex-col transition-all duration-300 flex-shrink-0 ${
            rightPanelCollapsed ? 'w-12' : 'w-[480px]'
          }`}
        >
          {/* Collapse toggle */}
          <button
            onClick={() => setRightPanelCollapsed(!rightPanelCollapsed)}
            className="absolute right-0 top-1/2 -translate-y-1/2 z-10 p-1 bg-dark-700 border border-dark-600 rounded-l-lg hover:bg-dark-600 transition-colors"
            style={{ marginRight: rightPanelCollapsed ? '48px' : '480px' }}
          >
            {rightPanelCollapsed ? (
              <ChevronLeft className="w-4 h-4 text-dark-400" />
            ) : (
              <ChevronRightIcon className="w-4 h-4 text-dark-400" />
            )}
          </button>
          
          {!rightPanelCollapsed && (
            <div className="flex-1 flex flex-col overflow-hidden">
              {/* Chat */}
              <div className="flex-1 overflow-hidden">
                {draft.draftId && (
                  <StudioChat
                    draftId={draft.draftId}
                    contextFiles={draft.contextFiles}
                    contextContent={draft.contextContent}
                    modelFiles={draft.modelFiles}
                    onSpecUpdated={refreshDraft}
                  />
                )}
              </div>
              
              {/* Config Panel (when node selected) */}
              <NodeConfigPanelV2 />
            </div>
          )}
          
          {rightPanelCollapsed && (
            <div className="flex flex-col items-center py-4 gap-4">
              <MessageSquare className="w-5 h-5 text-dark-400" />
            </div>
          )}
        </div>
      </div>
      
      {/* Notification Toast */}
      {notification && (
        <div
          className={`fixed bottom-4 right-4 flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg z-50 animate-slide-up ${
            notification.type === 'success'
              ? 'bg-green-500/10 border border-green-500/30 text-green-400'
              : notification.type === 'error'
              ? 'bg-red-500/10 border border-red-500/30 text-red-400'
              : 'bg-primary-500/10 border border-primary-500/30 text-primary-400'
          }`}
        >
          {notification.type === 'success' && <CheckCircle className="w-5 h-5" />}
          {notification.type === 'error' && <AlertCircle className="w-5 h-5" />}
          {notification.type === 'info' && <Sparkles className="w-5 h-5" />}
          <span>{notification.message}</span>
          <button
            onClick={() => setNotification(null)}
            className="p-1 hover:bg-white/10 rounded"
          >
            <X className="w-4 h-4" />
          </button>
        </div>
      )}
      
      {/* Build Dialog */}
      {showBuildDialog && draft.draftId && (
        <StudioBuildDialog
          draftId={draft.draftId}
          onClose={() => setShowBuildDialog(false)}
          onBuildComplete={handleBuildComplete}
        />
      )}
    </div>
  );
}
