/**
 * DICOM Viewer Controller using Cornerstone.js
 */
class DicomViewer {
  constructor() {
    console.log('[DICOM Viewer] DicomViewer constructor called');

    this.fileUrl = null;

    // Multi-viewport manager (replaces single viewport properties)
    this.viewportManager = null;

    // Folder browser support
    this.projectId = null;
    this.folders = [];
    this.currentFolderId = null;
    this.currentFolder = null; // Store full folder object with file metadata

    // Analysis support
    this.analysisRunning = false;
    this.currentAnalysis = null;
    this.selectedSeriesForAnalysis = []; // Array of {folderId, folderName, docIds}

    // Wait for libraries to load, then initialize
    if (typeof cornerstone !== 'undefined') {
      console.log('[DICOM Viewer] Cornerstone already loaded, initializing immediately...');
      this.initCornerstone();
    } else {
      console.log('[DICOM Viewer] Waiting for dicom-libraries-loaded event...');
      window.addEventListener('dicom-libraries-loaded', () => {
        console.log('[DICOM Viewer] dicom-libraries-loaded event received');
        this.initCornerstone();
      });
    }
  }

  async initCornerstone() {
    try {
      // Libraries are loaded sequentially by lib-loader.js, so they should be available
      console.log('[DICOM Viewer] Initializing Cornerstone...');

      // Verify all required libraries are loaded (lib-loader guarantees this, but double-check)
      const requiredLibs = {
        'cornerstone': cornerstone,
        'cornerstoneWADOImageLoader': cornerstoneWADOImageLoader,
        'dicomParser': dicomParser,
        'cornerstoneTools': cornerstoneTools,
        'cornerstoneMath': cornerstoneMath
      };

      const missing = Object.entries(requiredLibs)
        .filter(([name, lib]) => typeof lib === 'undefined')
        .map(([name]) => name);

      if (missing.length > 0) {
        throw new Error(`Required libraries not loaded: ${missing.join(', ')}. Check lib-loader.js`);
      }

      console.log('[DICOM Viewer] ✓ All libraries verified as loaded');
      
      // Configure Cornerstone WADO Image Loader
      console.log('[DICOM Viewer] Configuring WADO Image Loader...');
      cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
      cornerstoneWADOImageLoader.external.dicomParser = dicomParser;

      // Configure web worker and codec paths (using local bundled files)
      const codecPath = chrome.runtime.getURL('src/viewers/dicom/lib/');
      const workerPath = chrome.runtime.getURL('src/viewers/dicom/lib/cornerstoneWADOImageLoaderWebWorker.js');

      console.log('[DICOM Viewer] Worker path:', workerPath);
      console.log('[DICOM Viewer] Codec path:', codecPath);

      cornerstoneWADOImageLoader.webWorkerManager.initialize({
        maxWebWorkers: navigator.hardwareConcurrency || 4,
        startWebWorkersOnDemand: true,
        taskConfiguration: {
          decodeTask: {
            initializeCodecsOnStartup: false,
            usePDFJS: false,
            strict: false
          }
        }
      });

      // Set worker path (codecs are bundled in the worker file)
      cornerstoneWADOImageLoader.webWorkerManager.workerPath = workerPath;
      console.log('[DICOM Viewer] ✓ WADO Image Loader configured');

      // Configure cornerstoneTools external dependencies BEFORE initialization
      // This is CRITICAL - cornerstoneTools v6 requires these to be set before init()
      console.log('[DICOM Viewer] Configuring cornerstoneTools external dependencies...');

      if (!cornerstoneTools.external) {
        cornerstoneTools.external = {};
      }

      // Set required external dependencies
      cornerstoneTools.external.cornerstone = cornerstone;
      cornerstoneTools.external.cornerstoneMath = cornerstoneMath;

      // Some versions also need direct reference
      if (!cornerstoneTools.cornerstone) {
        cornerstoneTools.cornerstone = cornerstone;
      }

      // Verify dependencies are set correctly
      if (!cornerstoneTools.external.cornerstone) {
        throw new Error('Failed to set cornerstoneTools.external.cornerstone');
      }
      if (!cornerstoneTools.external.cornerstoneMath) {
        throw new Error('Failed to set cornerstoneTools.external.cornerstoneMath');
      }

      console.log('[DICOM Viewer] ✓ External dependencies configured');

      // CRITICAL WORKAROUND: Skip cornerstoneTools entirely
      // cornerstoneTools v6 has a SUPPORT_POINTER_EVENTS bug that cannot be fixed
      // We'll use cornerstone-core only for display
      console.log('[DICOM Viewer] ⚠️  Skipping cornerstoneTools due to v6 incompatibility');
      console.log('[DICOM Viewer] Image display will work via cornerstone-core');
      console.log('[DICOM Viewer] Interactive mouse tools will not be available (use toolbar buttons)');
      
      // Get file URL or series ID from query params
      const params = new URLSearchParams(window.location.search);
      this.fileUrl = params.get('file');
      this.seriesId = params.get('seriesId');
      this.projectId = params.get('projectId') ? parseInt(params.get('projectId')) : null;

      // Set up UI and initialize ViewportManager (async)
      await this.setupUI();

      // DO NOT enable element here - it will be enabled in loadFile() after tools are added
      // Enabling here causes SUPPORT_POINTER_EVENTS error because tools aren't ready yet

      // Load the initial file/series first (don't block on folder loading)
      if (this.seriesId) {
        // Load series from IndexedDB
        await this.loadSeries(this.seriesId);
      } else if (this.fileUrl) {
        // Load single file
        await this.loadFile(this.fileUrl);
      } else {
        this.showPlaceholder();
      }

      // Load project folders in the background after initial content is loaded
      if (this.projectId) {
        this.loadProjectFoldersInBackground();

        // Show analysis toggle button when projectId is present
        document.getElementById('analysis-toggle').style.display = 'flex';
      }
    } catch (error) {
      console.error('[DICOM Viewer] Failed to initialize Cornerstone:', error);
      console.error('[DICOM Viewer] Error stack:', error.stack);
      this.showError('Failed to initialize DICOM viewer: ' + error.message + 
        (error.message.includes('not loaded') ? 
          '\n\nLibraries must be bundled locally. See DICOM_VIEWER_BUNDLING.md' : 
          ''));
    }
  }

  async setupUI() {
    try {
      console.log('[DICOM Viewer] setupUI() starting...');

      // Verify Viewport class is available
      if (typeof Viewport === 'undefined') {
        throw new Error('Viewport class not loaded. Check lib-loader.js script order.');
      }
      console.log('[DICOM Viewer] ✓ Viewport class available');

      // Verify ViewportManager class is available
      if (typeof ViewportManager === 'undefined') {
        throw new Error('ViewportManager class not loaded. Check lib-loader.js script order.');
      }
      console.log('[DICOM Viewer] ✓ ViewportManager class available');

      // Initialize ViewportManager with grid container
      const gridContainer = document.getElementById('viewport-grid');
      if (!gridContainer) {
        throw new Error('Viewport grid container not found in HTML. Check viewer.html structure.');
      }
      console.log('[DICOM Viewer] ✓ Grid container found:', gridContainer);

      console.log('[DICOM Viewer] Creating ViewportManager...');
      this.viewportManager = new ViewportManager(gridContainer, this.projectId);
      console.log('[DICOM Viewer] ✓ ViewportManager instance created');

      // Wait for initial layout to be set up
      console.log('[DICOM Viewer] Setting initial layout to 1x1...');
      await this.viewportManager.setLayout('1x1');
      console.log('[DICOM Viewer] ✓ ViewportManager initialized with 1x1 layout');
    } catch (error) {
      console.error('[DICOM Viewer] setupUI() failed:', error);
      console.error('[DICOM Viewer] Error stack:', error.stack);
      throw error; // Re-throw to be caught by initCornerstone
    }

    // Set up viewport manager event callbacks
    this.viewportManager.onActiveViewportChangeCallback = (viewportId, viewport) => {
      console.log('[DICOM Viewer] Active viewport changed to:', viewportId);
      this.updateSeriesControls();
    };

    this.viewportManager.onViewportUpdateCallback = (viewportId, viewport) => {
      console.log('[DICOM Viewer] Viewport', viewportId, 'updated');
      this.updateSeriesControls();
    };

    // Set up layout controls
    this.setupLayoutControls();

    // Set up viewport controls
    this.setupViewportControls();

    // Set up tool button event listeners
    document.getElementById('close-btn').addEventListener('click', () => window.close());
    document.getElementById('zoom-in').addEventListener('click', () => this.zoomIn());
    document.getElementById('zoom-out').addEventListener('click', () => this.zoomOut());
    document.getElementById('fit-screen').addEventListener('click', () => this.fitToScreen());
    document.getElementById('rotate-left').addEventListener('click', () => this.rotate(-90));
    document.getElementById('rotate-right').addEventListener('click', () => this.rotate(90));
    document.getElementById('invert').addEventListener('click', () => this.toggleInvert());
    document.getElementById('reset').addEventListener('click', () => this.reset());
    document.getElementById('download-btn').addEventListener('click', () => this.download());

    // Series navigation buttons
    document.getElementById('prev-image-btn').addEventListener('click', () => this.previousImage());
    document.getElementById('next-image-btn').addEventListener('click', () => this.nextImage());

    // Thumbnail click navigation (event delegation)
    // TODO: Update for multi-viewport support
    document.getElementById('thumbnail-strip-inner').addEventListener('click', (e) => {
      const thumbnailItem = e.target.closest('.thumbnail-item');
      if (thumbnailItem && this.viewportManager) {
        const index = parseInt(thumbnailItem.dataset.index);
        const activeViewport = this.viewportManager.getActiveViewport();
        if (!isNaN(index) && activeViewport && activeViewport.currentImageIndex !== index) {
          activeViewport.loadImage(index);
        }
      }
    });

    // Help overlay
    document.getElementById('help-btn').addEventListener('click', () => this.showHelp());
    document.getElementById('help-close').addEventListener('click', () => this.hideHelp());
    document.getElementById('help-overlay').addEventListener('click', (e) => {
      if (e.target.id === 'help-overlay') this.hideHelp();
    });

    // Folder browser toggle and close
    document.getElementById('folder-browser-toggle').addEventListener('click', () => this.toggleFolderBrowser());
    document.getElementById('folder-browser-close').addEventListener('click', () => this.toggleFolderBrowser());

    // Analysis panel toggle and close
    document.getElementById('analysis-toggle').addEventListener('click', () => this.toggleAnalysisPanel());
    document.getElementById('analysis-panel-close').addEventListener('click', () => this.toggleAnalysisPanel());

    // Run analysis button
    document.getElementById('run-analysis-button').addEventListener('click', () => this.startAnalysis());

    // Clear and Select All buttons for series selection
    document.getElementById('clear-selection-button').addEventListener('click', () => this.clearAllSeriesSelection());
    document.getElementById('select-all-button').addEventListener('click', () => this.selectAllSeries());

    // Mouse wheel: Ctrl+Scroll = zoom, Shift+Scroll = contrast, regular scroll = navigate series
    // Attach to grid container to work with all viewports
    const gridContainer = document.getElementById('viewport-grid');
    if (gridContainer) {
      gridContainer.addEventListener('wheel', (e) => {
        console.log('[DICOM Viewer] Wheel event:', {
          ctrlKey: e.ctrlKey,
          metaKey: e.metaKey,
          shiftKey: e.shiftKey,
          deltaY: e.deltaY
        });

        e.preventDefault();

        // Ctrl/Cmd + Scroll = Zoom in/out
        if (e.ctrlKey || e.metaKey) {
          console.log('[DICOM Viewer] Ctrl+Scroll detected');
          if (e.deltaY < 0) {
            // Scroll up with Ctrl = zoom in
            this.zoomIn();
          } else if (e.deltaY > 0) {
            // Scroll down with Ctrl = zoom out
            this.zoomOut();
          }
        }
        // Shift + Scroll = Adjust brightness/black-white balance (window center)
        else if (e.shiftKey) {
          // Log the raw values to understand what the hardware is sending
          console.log('[DICOM Viewer] Shift+Scroll detected', {
            deltaY: e.deltaY,
            deltaX: e.deltaX,
            wheelDelta: e.wheelDelta,
            wheelDeltaY: e.wheelDeltaY
          });

          // Try multiple delta sources for better hardware compatibility
          let delta = e.deltaY;
          if (delta === 0 || Object.is(delta, -0) || Object.is(delta, 0)) {
            // Try wheelDeltaY as fallback (opposite sign convention)
            delta = e.wheelDeltaY ? -e.wheelDeltaY : e.deltaX;
          }

          if (delta !== 0 && !Object.is(delta, 0) && !Object.is(delta, -0)) {
            // Only adjust if we have a real direction
            const direction = delta > 0 ? -1 : 1; // Negative delta = scroll up = brighter
            this.adjustBrightness(direction);
          }
        }
        // Regular scroll = navigate through series (if series is loaded)
        else {
          const activeViewport = this.viewportManager?.getActiveViewport();
          if (activeViewport && activeViewport.hasContent() && activeViewport.seriesDocIds.length > 1) {
            console.log('[DICOM Viewer] Regular scroll - navigate series');
            if (e.deltaY > 0 || e.deltaX > 0) {
              // Scroll down/right = next image
              this.nextImage();
            } else if (e.deltaY < 0 || e.deltaX < 0) {
              // Scroll up/left = previous image
              this.previousImage();
            }
          } else {
            console.log('[DICOM Viewer] Scroll ignored - no series or no modifier key');
          }
        }
      }, { passive: false });
    }

    // Don't add tools here - wait until element is enabled
    // Tools will be added after cornerstone.enable() is called

    // Add keyboard shortcuts
    document.addEventListener('keydown', (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      
      switch(e.key) {
        case '+':
        case '=':
          e.preventDefault();
          this.zoomIn();
          break;
        case '-':
        case '_':
          e.preventDefault();
          this.zoomOut();
          break;
        case '0':
          e.preventDefault();
          this.fitToScreen();
          break;
        case 'r':
        case 'R':
          e.preventDefault();
          this.reset();
          break;
        case 'i':
        case 'I':
          e.preventDefault();
          this.toggleInvert();
          break;
        case '?':
          e.preventDefault();
          this.showHelp();
          break;
        case 'Escape':
          e.preventDefault();
          this.hideHelp();
          break;
        case 'ArrowLeft':
          e.preventDefault();
          // If series loaded, navigate to previous image; otherwise rotate
          const activeVpLeft = this.viewportManager?.getActiveViewport();
          if (activeVpLeft && activeVpLeft.hasContent() && activeVpLeft.seriesDocIds.length > 1) {
            this.previousImage();
          } else {
            this.rotate(-90);
          }
          break;
        case 'ArrowRight':
          e.preventDefault();
          // If series loaded, navigate to next image; otherwise rotate
          const activeVpRight = this.viewportManager?.getActiveViewport();
          if (activeVpRight && activeVpRight.hasContent() && activeVpRight.seriesDocIds.length > 1) {
            this.nextImage();
          } else {
            this.rotate(90);
          }
          break;
        case 'ArrowUp':
          e.preventDefault();
          const activeVpUp = this.viewportManager?.getActiveViewport();
          if (activeVpUp && activeVpUp.hasContent() && activeVpUp.seriesDocIds.length > 1) {
            this.previousImage();
          }
          break;
        case 'ArrowDown':
          e.preventDefault();
          const activeVpDown = this.viewportManager?.getActiveViewport();
          if (activeVpDown && activeVpDown.hasContent() && activeVpDown.seriesDocIds.length > 1) {
            this.nextImage();
          }
          break;
        case 'PageUp':
          e.preventDefault();
          const activeVpPageUp = this.viewportManager?.getActiveViewport();
          if (activeVpPageUp && activeVpPageUp.hasContent() && activeVpPageUp.seriesDocIds.length > 1) {
            this.previousImage();
          }
          break;
        case 'PageDown':
          e.preventDefault();
          const activeVpPageDown = this.viewportManager?.getActiveViewport();
          if (activeVpPageDown && activeVpPageDown.hasContent() && activeVpPageDown.seriesDocIds.length > 1) {
            this.nextImage();
          }
          break;
        case 'Escape':
          window.close();
          break;
        // Viewport selection: Keys 1-9 select viewport
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
          e.preventDefault();
          const viewportIndex = parseInt(e.key) - 1;
          if (this.viewportManager && viewportIndex < this.viewportManager.viewports.length) {
            this.viewportManager.setActiveViewport(viewportIndex);
            console.log('[DICOM Viewer] Switched to viewport', viewportIndex + 1, 'via keyboard');
          }
          break;
      }
    });
  }

  /**
   * Set up layout control buttons (1x1, 2x2, 3x3)
   */
  setupLayoutControls() {
    console.log('[DICOM Viewer] Setting up layout controls...');
    document.querySelectorAll('.layout-btn').forEach(btn => {
      btn.addEventListener('click', async () => {
        const layout = btn.dataset.layout;
        console.log('[DICOM Viewer] Layout button clicked:', layout);

        // Update active button state
        document.querySelectorAll('.layout-btn').forEach(b => b.classList.remove('active'));
        btn.classList.add('active');

        // Change layout
        await this.viewportManager.setLayout(layout);
      });
    });
  }

  /**
   * Set up viewport control buttons (link, clear)
   */
  setupViewportControls() {
    console.log('[DICOM Viewer] Setting up viewport controls...');

    // Link viewports button
    document.getElementById('link-viewports-btn').addEventListener('click', () => {
      const linked = this.viewportManager.toggleLinkedMode();
      document.getElementById('link-viewports-btn').classList.toggle('active', linked);
      console.log('[DICOM Viewer] Linked mode:', linked ? 'ON' : 'OFF');
    });

    // Clear viewport button
    document.getElementById('clear-viewport-btn').addEventListener('click', () => {
      this.viewportManager.clearActiveViewport();
      console.log('[DICOM Viewer] Active viewport cleared');
    });
  }

  async loadFile(url) {
    try {
      document.getElementById('loading').style.display = 'block';
      document.getElementById('placeholder').style.display = 'none';
      document.getElementById('error').style.display = 'none';
      
      // Handle data URLs and direct URLs - convert to File object for Cornerstone
      let file;
      const params = new URLSearchParams(window.location.search);
      const isDirect = params.get('direct') === 'true';
      
      if (url.startsWith('data:')) {
        // Convert data URL to File object
        const base64 = url.split(',')[1];
        const mimeType = url.split(';')[0].split(':')[1] || 'application/dicom';
        const binaryString = atob(base64);
        const bytes = new Uint8Array(binaryString.length);
        for (let i = 0; i < binaryString.length; i++) {
          bytes[i] = binaryString.charCodeAt(i);
        }
        const blob = new Blob([bytes], { type: mimeType });
        file = new File([blob], 'dicom.dcm', { type: mimeType });
      } else {
        // Fetch from URL (either direct Filevine URL or blob URL)
        // For direct URLs, we need to include credentials/cookies
        console.log('[DICOM Viewer] Fetching file from URL:', url.substring(0, 100) + '...');
        const fetchOptions = {
          credentials: 'include' // Include cookies for authenticated requests
        };
        
        const response = await fetch(url, fetchOptions);
        console.log('[DICOM Viewer] Fetch response status:', response.status, response.statusText);
        
        if (!response.ok) {
          const errorText = await response.text().catch(() => 'Unknown error');
          throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}. ${errorText.substring(0, 200)}`);
        }
        
        const blob = await response.blob();
        console.log('[DICOM Viewer] File fetched successfully, size:', blob.size, 'bytes, type:', blob.type);
        const filename = url.split('/').pop() || 'dicom.dcm';
        file = new File([blob], filename, { type: blob.type || 'application/dicom' });
        console.log('[DICOM Viewer] Created File object:', filename, file.size, 'bytes');
      }

      // Add file to Cornerstone file manager and load image
      console.log('[DICOM Viewer] Adding file to Cornerstone file manager...');
      const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(file);
      console.log('[DICOM Viewer] Image ID:', imageId);
      console.log('[DICOM Viewer] Loading image with Cornerstone...');
      const image = await cornerstone.loadImage(imageId);
      console.log('[DICOM Viewer] Image loaded successfully:', image.width, 'x', image.height);

      // Store image reference
      this.image = image;

      // WORKAROUND for cornerstoneTools v6 SUPPORT_POINTER_EVENTS bug:
      // The issue: cornerstoneTools.init() wraps cornerstone.enable() and tries to access
      // window.PointerEvent.SUPPORT_POINTER_EVENTS which doesn't exist
      //
      // Solution: Create viewport manually and use displayImage() without calling enable()
      // displayImage() will enable the element internally without going through cornerstoneTools

      // Step 1: Create viewport manually (can't use getDefaultViewportForImage - needs enabled element)
      console.log('[DICOM Viewer] Creating viewport manually...');
      const windowWidth = (image.maxPixelValue !== undefined && image.minPixelValue !== undefined)
        ? image.maxPixelValue - image.minPixelValue
        : 256;
      const windowCenter = (image.maxPixelValue !== undefined && image.minPixelValue !== undefined)
        ? (image.maxPixelValue + image.minPixelValue) / 2
        : 128;

      // Calculate scale to fit image to viewport
      const canvas = this.element;

      // CRITICAL: Get parent dimensions and set canvas explicitly
      const parent = canvas.parentElement;
      const parentWidth = parent.clientWidth;
      const parentHeight = parent.clientHeight;

      console.log('[DICOM Viewer] Parent (.viewer-container) dimensions:', parentWidth, 'x', parentHeight);

      // Set canvas to exact parent size with explicit pixel values
      canvas.style.width = parentWidth + 'px';
      canvas.style.height = parentHeight + 'px';

      // Force layout recalculation
      canvas.offsetHeight; // Force reflow

      // Get canvas dimensions after explicit sizing
      let canvasWidth = canvas.clientWidth;
      let canvasHeight = canvas.clientHeight;

      console.log('[DICOM Viewer] Canvas dimensions after explicit sizing:', canvasWidth, 'x', canvasHeight);

      // Verify we have valid dimensions
      if (!canvasWidth || !canvasHeight || canvasWidth < 100 || canvasHeight < 100) {
        console.error('[DICOM Viewer] Invalid canvas dimensions! Using window fallback.');
        canvasWidth = window.innerWidth - 40;
        canvasHeight = window.innerHeight - 150;
        console.log('[DICOM Viewer] Fallback dimensions:', canvasWidth, 'x', canvasHeight);
      }

      let scale;

      // If this is part of a series and we have a base scale, use it for consistency
      if (this.seriesDocIds.length > 1 && this.seriesBaseScale !== null) {
        scale = this.seriesBaseScale;
        console.log('[DICOM Viewer] Using series base scale:', scale.toFixed(2));
      } else {
        // Calculate scale for first image in series (or single image)
        const imageAspectRatio = image.width / image.height;
        const canvasAspectRatio = canvasWidth / canvasHeight;

        if (imageAspectRatio > canvasAspectRatio) {
          // Image is wider than canvas - fit to width
          scale = canvasWidth / image.width;
        } else {
          // Image is taller than canvas - fit to height
          scale = canvasHeight / image.height;
        }

        // Apply margin and make images fill more space (but stay within bounds)
        scale *= 0.98; // 98% to stay within canvas with minimal margin

        // Store this as the base scale for the series
        if (this.seriesDocIds.length > 1) {
          this.seriesBaseScale = scale;
          console.log('[DICOM Viewer] Stored series base scale:', scale.toFixed(2));
        }

        console.log('[DICOM Viewer] Calculated scale - Image:', image.width, 'x', image.height,
                    'Canvas:', canvasWidth, 'x', canvasHeight, 'Scale:', scale.toFixed(2));
      }

      this.viewport = {
        scale: scale,
        translation: { x: 0, y: 0 },
        voi: {
          windowWidth: windowWidth,
          windowCenter: windowCenter
        },
        invert: false,
        pixelReplication: false,
        rotation: 0,
        hflip: false,
        vflip: false,
        modalityLUT: image.modalityLUT,
        voiLUT: image.voiLUT,
        colormap: undefined,
        labelmap: false
      };

      // Store window/level values
      this.windowWidth = windowWidth;
      this.windowCenter = windowCenter;

      console.log('[DICOM Viewer] Viewport created - W:', windowWidth, 'L:', windowCenter);

      // Step 2: Enable element (SUPPORT_POINTER_EVENTS should be polyfilled now)
      try {
        console.log('[DICOM Viewer] Enabling element...');
        cornerstone.enable(this.element);
        console.log('[DICOM Viewer] ✓ Element enabled successfully');

        // Force cornerstone to resize its internal canvas to match the container
        cornerstone.resize(this.element, true);
        console.log('[DICOM Viewer] ✓ Canvas resized to match container');
      } catch (enableError) {
        console.error('[DICOM Viewer] Failed to enable element:', enableError);
        console.error('[DICOM Viewer] Stack:', enableError.stack);
        throw new Error('Failed to enable element: ' + enableError.message);
      }

      // Step 3: Display the image (element is now enabled)
      try {
        console.log('[DICOM Viewer] Displaying image...');
        cornerstone.displayImage(this.element, image, this.viewport);
        console.log('[DICOM Viewer] ✓ Image displayed successfully');
      } catch (displayError) {
        console.error('[DICOM Viewer] Failed to display image:', displayError);
        console.error('[DICOM Viewer] Stack:', displayError.stack);
        throw new Error('Failed to display image: ' + displayError.message);
      }

      // Step 4: Skip interactive tools for now due to cornerstoneTools v6 bugs
      // The toolbar buttons (zoom, rotate, etc.) will still work via programmatic viewport changes
      console.log('[DICOM Viewer] Skipping interactive mouse tools (cornerstoneTools v6 compatibility issues)');
      console.log('[DICOM Viewer] Toolbar buttons will work for zoom, rotate, window/level adjustments');
      
      // Listen for viewport changes to update UI
      this.element.addEventListener('cornerstoneimagerendered', () => {
        this.updateStatusBar();
      });
      
      // Update UI with DICOM metadata
      this.updateMetadata(image);
      
      // Extract filename from URL and display
      try {
        if (url.startsWith('data:')) {
          document.getElementById('filename').textContent = 'DICOM Image';
        } else {
          const urlObj = new URL(url);
          const filename = urlObj.pathname.split('/').pop() || 'DICOM Image';
          document.getElementById('filename').textContent = filename;
        }
      } catch {
        document.getElementById('filename').textContent = 'DICOM Image';
      }

      // Update status bar
      this.updateStatusBar();

    } catch (error) {
      console.error('Failed to load DICOM file:', error);
      this.showError(error.message || 'Failed to load DICOM file');
    } finally {
      document.getElementById('loading').style.display = 'none';
    }
  }

  updateMetadata(image) {
    // Try to extract DICOM metadata from image data
    let patientName = '-';
    let studyDate = '-';
    let modality = '-';
    
    try {
      // Access DICOM data if available
      if (image.data && typeof image.data.string === 'function') {
        patientName = image.data.string('x00100010') || '-';
        studyDate = image.data.string('x00080020') || '-';
        modality = image.data.string('x00080060') || '-';
      }
    } catch (e) {
      console.log('Could not extract DICOM metadata:', e);
    }
    
    const imageSize = image.width && image.height ? `${image.width} × ${image.height}` : '-';

    document.getElementById('patient-name').textContent = patientName;
    document.getElementById('study-date').textContent = studyDate;
    document.getElementById('modality').textContent = modality;
    document.getElementById('image-size').textContent = imageSize;
    
    document.getElementById('info-panel').style.display = 'block';
  }

  updateStatusBar() {
    if (!this.viewport) return;
    
    const zoom = Math.round((this.viewport.scale || 1) * 100);
    document.getElementById('zoom-level').textContent = `Zoom: ${zoom}%`;
    
    if (this.viewport.voi && this.viewport.voi.windowWidth) {
      const wl = `W: ${Math.round(this.viewport.voi.windowWidth)} / L: ${Math.round(this.viewport.voi.windowCenter || 0)}`;
      document.getElementById('window-level').textContent = wl;
    } else {
      document.getElementById('window-level').textContent = 'W/L: - / -';
    }
    
    // Update position if available
    if (this.viewport.translation) {
      const pos = `X: ${Math.round(this.viewport.translation.x || 0)} / Y: ${Math.round(this.viewport.translation.y || 0)}`;
      document.getElementById('position').textContent = pos;
    }
  }

  async loadSeries(seriesId) {
    try {
      console.log('[DICOM Viewer] Loading series:', seriesId);
      document.getElementById('loading').style.display = 'block';
      document.getElementById('placeholder').style.display = 'none';
      document.getElementById('error').style.display = 'none';

      if (!this.viewportManager) {
        throw new Error('ViewportManager not initialized');
      }

      // Send message to background script to get series data
      const response = await chrome.runtime.sendMessage({
        type: 'GET_SERIES',
        seriesId: seriesId
      });

      if (!response || !response.series) {
        throw new Error('Series not found');
      }

      const series = response.series;
      const docIds = series.docIds || [];

      console.log('[DICOM Viewer] Series contains', docIds.length, 'images');

      if (docIds.length === 0) {
        throw new Error('Series has no images');
      }

      // Load series into active viewport (viewport 0 by default)
      await this.viewportManager.loadSeriesIntoActiveViewport(
        seriesId,
        docIds,
        {
          folderName: series.description || 'Initial Series',
          folderId: seriesId,
          files: docIds.map(docId => ({ docId }))
        }
      );

      // Hide loading state
      document.getElementById('loading').style.display = 'none';

      // Update series UI
      this.updateSeriesControls();

      // Auto-select this series for analysis
      const seriesSelection = {
        folderId: seriesId,
        folderName: series.description || 'Initial Series',
        docIds: docIds
      };

      // Add to selected series if not already present
      const isAlreadySelected = this.selectedSeriesForAnalysis.some(s => s.folderId === seriesId);
      if (!isAlreadySelected) {
        this.selectedSeriesForAnalysis.push(seriesSelection);
        this.updateSelectedSeriesList();
        console.log('[DICOM Viewer] Initial series auto-selected for analysis:', seriesId, '- Images:', docIds.length);
      }

    } catch (error) {
      console.error('[DICOM Viewer] Failed to load series:', error);
      document.getElementById('loading').style.display = 'none';
      this.showError('Failed to load DICOM series: ' + error.message);
    }
  }

  async loadImageFromSeries(index) {
    try {
      if (index < 0 || index >= this.seriesDocIds.length) {
        console.error('[DICOM Viewer] Invalid image index:', index);
        return;
      }

      const docId = this.seriesDocIds[index];
      console.log('[DICOM Viewer] Loading image', index + 1, 'of', this.seriesDocIds.length, '- docId:', docId);

      // Get file metadata from current folder if available
      let fileMetadata = null;
      if (this.currentFolder && this.currentFolder.files) {
        fileMetadata = this.currentFolder.files.find(f => f.docId === docId);
      }

      // Get file from cache or download from Filevine
      const response = await chrome.runtime.sendMessage({
        type: 'GET_FILE',
        docId: docId,
        projectId: this.projectId, // Needed for on-demand download
        filename: fileMetadata?.filename,
        folderPath: this.currentFolder?.folderPath || [],
        mimeType: fileMetadata?.mimeType || 'application/dicom'
      });

      if (!response || !response.file) {
        throw new Error(response?.error || 'Image file not found');
      }

      // Background script already converted blob to data URL
      const dataUrl = response.file.dataUrl;

      // Load the image using existing loadFile logic
      await this.loadFile(dataUrl);

      // Update series UI
      this.currentImageIndex = index;
      this.updateSeriesControls();

    } catch (error) {
      console.error('[DICOM Viewer] Failed to load image from series:', error);
      this.showError('Failed to load image ' + (index + 1) + ': ' + error.message);
    }
  }

  blobToDataUrl(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result);
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    });
  }

  nextImage() {
    if (!this.viewportManager) return;
    this.viewportManager.nextImage();
  }

  previousImage() {
    if (!this.viewportManager) return;
    this.viewportManager.previousImage();
  }

  async generateThumbnails() {
    try {
      console.log('[DICOM Viewer] Generating thumbnails for', this.seriesDocIds.length, 'images');
      const thumbnailStrip = document.getElementById('thumbnail-strip');
      const thumbnailStripInner = document.getElementById('thumbnail-strip-inner');

      if (!thumbnailStrip || !thumbnailStripInner) {
        console.error('[DICOM Viewer] Thumbnail strip elements not found');
        return;
      }

      // Show thumbnail strip
      thumbnailStrip.style.display = 'block';

      // Clear existing thumbnails
      thumbnailStripInner.innerHTML = '';
      this.thumbnails = [];

      // Generate thumbnail for each image
      for (let i = 0; i < this.seriesDocIds.length; i++) {
        const docId = this.seriesDocIds[i];

        // Create thumbnail container
        const thumbnailItem = document.createElement('div');
        thumbnailItem.className = 'thumbnail-item';
        thumbnailItem.dataset.index = i;
        if (i === this.currentImageIndex) {
          thumbnailItem.classList.add('active');
        }

        // Add loading text
        const loadingText = document.createElement('div');
        loadingText.className = 'thumbnail-loading';
        loadingText.textContent = 'Loading...';
        thumbnailItem.appendChild(loadingText);

        // Add image number
        const numberLabel = document.createElement('div');
        numberLabel.className = 'thumbnail-number';
        numberLabel.textContent = i + 1;
        thumbnailItem.appendChild(numberLabel);

        thumbnailStripInner.appendChild(thumbnailItem);

        // Load and render thumbnail asynchronously
        this.renderThumbnail(docId, i, thumbnailItem);
      }
    } catch (error) {
      console.error('[DICOM Viewer] Failed to generate thumbnails:', error);
    }
  }

  async renderThumbnail(docId, index, thumbnailItem) {
    try {
      console.log('[DICOM Viewer] Rendering thumbnail', index + 1, 'for docId:', docId);

      // Get file metadata from current folder if available
      let fileMetadata = null;
      if (this.currentFolder && this.currentFolder.files) {
        fileMetadata = this.currentFolder.files.find(f => f.docId === docId);
      }

      // Get file from cache or download from Filevine
      const response = await chrome.runtime.sendMessage({
        type: 'GET_FILE',
        docId: docId,
        projectId: this.projectId, // Needed for on-demand download
        filename: fileMetadata?.filename,
        folderPath: this.currentFolder?.folderPath || [],
        mimeType: fileMetadata?.mimeType || 'application/dicom'
      });

      if (!response || !response.file) {
        throw new Error(response?.error || 'Image file not found');
      }

      const dataUrl = response.file.dataUrl;
      console.log('[DICOM Viewer] Got file data for thumbnail', index + 1);

      // Convert data URL to File object for Cornerstone
      const base64 = dataUrl.split(',')[1];
      const mimeType = dataUrl.split(';')[0].split(':')[1] || 'application/dicom';
      const binaryString = atob(base64);
      const bytes = new Uint8Array(binaryString.length);
      for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
      }
      const blob = new Blob([bytes], { type: mimeType });
      const file = new File([blob], 'dicom.dcm', { type: mimeType });

      // Load image with Cornerstone
      const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(file);
      const image = await cornerstone.loadImage(imageId);
      console.log('[DICOM Viewer] Loaded DICOM image for thumbnail', index + 1, '- size:', image.width, 'x', image.height);

      // Create a temporary canvas element for rendering
      const tempCanvas = document.createElement('canvas');
      tempCanvas.width = 80;
      tempCanvas.height = 80;

      // Add canvas to DOM temporarily (required for Cornerstone)
      tempCanvas.style.position = 'absolute';
      tempCanvas.style.left = '-9999px';
      document.body.appendChild(tempCanvas);

      try {
        // Enable the canvas element for Cornerstone
        cornerstone.enable(tempCanvas);
        console.log('[DICOM Viewer] Enabled Cornerstone on temp canvas for thumbnail', index + 1);

        // Calculate scale to fit image in thumbnail
        const scale = Math.min(80 / image.width, 80 / image.height);

        // Create viewport for thumbnail
        const viewport = {
          scale: scale,
          translation: { x: 0, y: 0 },
          voi: {
            windowWidth: (image.maxPixelValue - image.minPixelValue) || 256,
            windowCenter: ((image.maxPixelValue + image.minPixelValue) / 2) || 128
          },
          invert: false,
          pixelReplication: false,
          rotation: 0,
          hflip: false,
          vflip: false
        };

        console.log('[DICOM Viewer] Rendering thumbnail', index + 1, 'with viewport:', viewport);

        // Render thumbnail with Cornerstone
        cornerstone.displayImage(tempCanvas, image, viewport);

        // Wait a bit for rendering to complete
        await new Promise(resolve => setTimeout(resolve, 100));

        // Get the rendered canvas from Cornerstone
        const renderedCanvas = cornerstone.getEnabledElement(tempCanvas).canvas;
        console.log('[DICOM Viewer] Got rendered canvas for thumbnail', index + 1);

        // Convert to data URL
        const thumbnailDataUrl = renderedCanvas.toDataURL('image/png');
        console.log('[DICOM Viewer] Converted thumbnail', index + 1, 'to data URL, length:', thumbnailDataUrl.length);

        // Create image element
        const imgElement = document.createElement('img');
        imgElement.src = thumbnailDataUrl;

        // Handle image load
        imgElement.onload = () => {
          console.log('[DICOM Viewer] Thumbnail image', index + 1, 'loaded successfully');
        };

        imgElement.onerror = (e) => {
          console.error('[DICOM Viewer] Failed to load thumbnail image', index + 1, ':', e);
        };

        // Remove loading text
        const loadingText = thumbnailItem.querySelector('.thumbnail-loading');
        if (loadingText) {
          loadingText.remove();
        }

        // Add image to thumbnail
        thumbnailItem.insertBefore(imgElement, thumbnailItem.firstChild);

        // Store thumbnail data
        this.thumbnails[index] = {
          image: image,
          dataUrl: thumbnailDataUrl
        };

        console.log('[DICOM Viewer] Thumbnail', index + 1, 'generated successfully');

      } finally {
        // Clean up: disable and remove temporary canvas
        try {
          cornerstone.disable(tempCanvas);
        } catch (e) {
          console.warn('[DICOM Viewer] Failed to disable temp canvas:', e);
        }
        document.body.removeChild(tempCanvas);
      }

    } catch (error) {
      console.error('[DICOM Viewer] Failed to render thumbnail', index + 1, ':', error);
      console.error('[DICOM Viewer] Error stack:', error.stack);

      // Show error in thumbnail
      const loadingText = thumbnailItem.querySelector('.thumbnail-loading');
      if (loadingText) {
        loadingText.textContent = 'Error';
        loadingText.style.color = '#ff6b6b';
      }
    }
  }

  updateThumbnailStrip() {
    // Update active thumbnail highlighting
    const thumbnailItems = document.querySelectorAll('.thumbnail-item');
    thumbnailItems.forEach((item, index) => {
      if (index === this.currentImageIndex) {
        item.classList.add('active');
        // Scroll thumbnail into view
        item.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
      } else {
        item.classList.remove('active');
      }
    });
  }

  updateSeriesControls() {
    const seriesControls = document.getElementById('series-controls');
    const seriesDivider = document.getElementById('series-divider');
    const imageCounter = document.getElementById('image-counter');
    const prevBtn = document.getElementById('prev-image-btn');
    const nextBtn = document.getElementById('next-image-btn');

    if (!this.viewportManager) {
      // Hide series controls if no viewport manager
      if (seriesControls) seriesControls.style.display = 'none';
      if (seriesDivider) seriesDivider.style.display = 'none';
      return;
    }

    // Get active viewport info
    const activeViewport = this.viewportManager.getActiveViewport();
    if (!activeViewport || !activeViewport.hasContent()) {
      // Hide series controls if no active viewport or no content
      if (seriesControls) seriesControls.style.display = 'none';
      if (seriesDivider) seriesDivider.style.display = 'none';
      return;
    }

    const seriesInfo = activeViewport.getSeriesInfo();
    if (seriesInfo.imageCount > 1) {
      // Show series controls
      if (seriesControls) seriesControls.style.display = 'flex';
      if (seriesDivider) seriesDivider.style.display = 'block';
      if (imageCounter) {
        imageCounter.textContent = `${seriesInfo.currentImageIndex + 1} / ${seriesInfo.imageCount}`;
      }

      // Enable/disable buttons
      if (prevBtn) prevBtn.disabled = false;
      if (nextBtn) nextBtn.disabled = false;
    } else {
      // Hide series controls for single image
      if (seriesControls) seriesControls.style.display = 'none';
      if (seriesDivider) seriesDivider.style.display = 'none';
    }

    // Update thumbnail strip highlighting (TODO: update for multi-viewport)
    // this.updateThumbnailStrip();
  }

  showPlaceholder() {
    document.getElementById('loading').style.display = 'none';
    document.getElementById('error').style.display = 'none';
    document.getElementById('placeholder').style.display = 'block';
  }

  showError(message) {
    document.getElementById('loading').style.display = 'none';
    document.getElementById('placeholder').style.display = 'none';
    document.getElementById('error').style.display = 'block';
    document.getElementById('error-message').textContent = message;
  }

  zoomIn() {
    if (!this.viewportManager) return;
    this.viewportManager.zoomIn();
    this.updateStatusBar();
  }

  zoomOut() {
    if (!this.viewportManager) return;
    this.viewportManager.zoomOut();
    this.updateStatusBar();
  }

  adjustBrightness(delta) {
    // Adjust window center (brightness/black-white balance) incrementally
    if (!this.viewportManager) return;

    const activeViewport = this.viewportManager.getActiveViewport();
    if (!activeViewport || !activeViewport.viewport || !activeViewport.viewport.voi) return;

    const currentWidth = activeViewport.viewport.voi.windowWidth;
    const currentCenter = activeViewport.viewport.voi.windowCenter;

    // Adjust by 5% of window width, minimum 10 units
    const adjustment = Math.max(Math.abs(currentWidth * 0.05), 10);

    const newCenter = currentCenter + (delta * adjustment);

    console.log('[DICOM Viewer] Brightness adjusted:', {
      delta,
      adjustment: adjustment.toFixed(1),
      oldCenter: currentCenter.toFixed(1),
      newCenter: newCenter.toFixed(1),
      windowWidth: currentWidth.toFixed(1)
    });

    activeViewport.adjustWindowCenter(delta * adjustment);
    this.updateStatusBar();
  }

  adjustContrast(delta) {
    // Adjust window width (contrast range) incrementally
    if (!this.viewportManager) return;

    const activeViewport = this.viewportManager.getActiveViewport();
    if (!activeViewport || !activeViewport.viewport || !activeViewport.viewport.voi) return;

    const currentWidth = activeViewport.viewport.voi.windowWidth;
    // Adjust by 5% of current width, minimum 10 units
    const adjustment = Math.max(Math.abs(currentWidth * 0.05), 10);

    activeViewport.adjustWindowWidth(delta * adjustment);
    this.updateStatusBar();
  }

  fitToScreen() {
    if (!this.viewportManager) return;
    this.viewportManager.reset();
    this.updateStatusBar();
  }

  rotate(degrees) {
    if (!this.viewportManager) return;
    if (degrees === 90 || degrees === -90) {
      this.viewportManager.rotate(); // Rotate 90 degrees clockwise
    }
  }

  toggleInvert() {
    if (!this.viewportManager) return;
    this.viewportManager.toggleInvert();

    // Update button state based on active viewport
    const activeViewport = this.viewportManager.getActiveViewport();
    if (activeViewport) {
      document.getElementById('invert').classList.toggle('active', activeViewport.inverted);
    }
  }

  reset() {
    if (!this.viewportManager) return;
    this.viewportManager.reset();

    // Update invert button state
    const activeViewport = this.viewportManager.getActiveViewport();
    if (activeViewport) {
      document.getElementById('invert').classList.toggle('active', activeViewport.inverted);
    }
    this.updateStatusBar();
  }

  showHelp() {
    document.getElementById('help-overlay').style.display = 'flex';
  }

  hideHelp() {
    document.getElementById('help-overlay').style.display = 'none';
  }

  /**
   * Load project folders in the background without blocking initial viewer load
   */
  loadProjectFoldersInBackground() {
    console.log('[DICOM Viewer] 📂 Starting background folder tree load for project:', this.projectId);

    // Show the toggle button immediately so user knows the feature exists
    document.getElementById('folder-browser-toggle').style.display = 'flex';

    // Load folders asynchronously
    this.loadProjectFolders().catch(error => {
      console.error('[DICOM Viewer] Background folder loading failed:', error);
    });
  }

  /**
   * Load all DICOM folders for the current project
   */
  async loadProjectFolders() {
    if (!this.projectId) {
      console.log('[DICOM Viewer] ⚠️  No project ID in URL, folder browser disabled');
      console.log('[DICOM Viewer] Current URL:', window.location.href);
      return;
    }

    try {
      console.log('[DICOM Viewer] 📂 Loading DICOM folders for project:', this.projectId);

      const response = await chrome.runtime.sendMessage({
        type: 'GET_PROJECT_DICOM_FILES',
        projectId: this.projectId
      });

      console.log('[DICOM Viewer] Response from background:', response);

      if (!response || !response.files) {
        throw new Error('Failed to load project folders: ' + (response?.error || 'No response'));
      }

      this.folders = response.files;
      console.log('[DICOM Viewer] ✅ Loaded', this.folders.length, 'folders');

      // Always show folder browser toggle button when projectId is present
      // Even if no folders found, we want to show the UI so user knows the feature exists
      document.getElementById('folder-browser-toggle').style.display = 'flex';
      console.log('[DICOM Viewer] 📁 Folder browser toggle button shown');

      // Populate folder browser (will show empty state if no folders)
      this.populateFolderBrowser();

    } catch (error) {
      console.error('[DICOM Viewer] ❌ Failed to load project folders:', error);
      console.error('[DICOM Viewer] Error details:', error.message, error.stack);

      // Still show the toggle button even on error
      document.getElementById('folder-browser-toggle').style.display = 'flex';

      // Show error in folder browser
      const content = document.getElementById('folder-browser-content');
      if (content) {
        content.innerHTML = `
          <div class="folder-browser-empty">
            <div style="margin-bottom: 10px; font-size: 14px; font-weight: 500; color: #ff6b6b;">Error loading folders</div>
            <div style="font-size: 12px; color: #666; line-height: 1.4;">
              ${this.escapeHtml(error.message)}
              <br><br>
              Check the browser console for more details.
            </div>
          </div>
        `;
      }
    }
  }

  /**
   * Populate the folder browser sidebar
   */
  populateFolderBrowser() {
    const content = document.getElementById('folder-browser-content');

    if (!content) {
      console.warn('[DICOM Viewer] folder-browser-content element not found');
      return;
    }

    if (!this.folders || this.folders.length === 0) {
      content.innerHTML = `
        <div class="folder-browser-empty">
          <div style="margin-bottom: 10px; font-size: 14px; font-weight: 500;">No folders found</div>
          <div style="font-size: 12px; color: #666; line-height: 1.4;">
            This project doesn't contain any folders.
          </div>
        </div>
      `;
      return;
    }

    content.innerHTML = '';

    console.log('[DICOM Viewer] 📁 Rendering', this.folders.length, 'folders in browser');

    // Initialize collapsed state if not already set
    if (!this.collapsedFolders) {
      this.collapsedFolders = new Set();
      // Start with all folders collapsed by default
      this.folders.forEach(folder => {
        if (this.hasChildren(folder)) {
          this.collapsedFolders.add(folder.folderId);
        }
      });
    }

    // Build parent-child relationship map
    const childToParent = new Map();
    this.folders.forEach(folder => {
      const children = this.getChildFolders(folder);
      children.forEach(child => {
        childToParent.set(child.folderId, folder.folderId);
      });
    });

    // Filter folders to only show those whose parents are expanded
    const visibleFolders = this.folders.filter(folder => {
      // Root level folders are always visible
      if (folder.depth === 0) return true;

      // Check if all ancestors are expanded
      let parentId = childToParent.get(folder.folderId);
      while (parentId !== undefined) {
        if (this.collapsedFolders.has(parentId)) {
          return false; // Parent is collapsed, hide this folder
        }
        parentId = childToParent.get(parentId);
      }
      return true;
    });

    console.log('[DICOM Viewer] 👁️  Showing', visibleFolders.length, 'of', this.folders.length, 'folders');

    for (const folder of visibleFolders) {
      const folderItem = document.createElement('div');
      folderItem.className = 'folder-item';
      folderItem.dataset.folderId = folder.folderId;

      // Apply indentation based on folder depth
      const depth = folder.depth || 0;
      const indentPx = depth * 16; // 16px per level
      folderItem.style.paddingLeft = `${12 + indentPx}px`;

      const fileCount = folder.files ? folder.files.length : 0;
      const fileLabel = fileCount === 1 ? 'file' : 'files';

      // Remove spaces from folderName since we're using CSS padding for indentation
      const displayName = folder.folderName.trimStart();

      // Determine if this folder has children
      const hasChildren = this.hasChildren(folder);
      const isCollapsed = this.collapsedFolders.has(folder.folderId);
      const expandIcon = hasChildren ? (isCollapsed ? '▶' : '▼') : '';

      // Check if this series is selected for analysis
      const isSelected = this.selectedSeriesForAnalysis.some(s => s.folderId === folder.folderId);

      folderItem.innerHTML = `
        ${hasChildren ? `<div class="folder-expand-icon" data-folder-id="${folder.folderId}">${expandIcon}</div>` : '<div class="folder-expand-icon" style="width: 16px;"></div>'}
        <div class="folder-item-checkbox ${isSelected ? 'checked' : ''}" data-folder-id="${folder.folderId}"></div>
        <div class="folder-item-icon">📂</div>
        <div class="folder-item-content">
          <div class="folder-item-name">${this.escapeHtml(displayName)}</div>
          <div class="folder-item-count">${fileCount} ${fileLabel}</div>
        </div>
      `;

      // Click handler for expand/collapse icon
      if (hasChildren) {
        const expandIconEl = folderItem.querySelector('.folder-expand-icon');
        expandIconEl.addEventListener('click', (e) => {
          e.stopPropagation(); // Prevent folder load
          this.toggleFolderCollapse(folder.folderId);
        });
        expandIconEl.style.cursor = 'pointer';
      }

      // Click handler for checkbox (toggle selection for analysis)
      const checkboxEl = folderItem.querySelector('.folder-item-checkbox');
      checkboxEl.addEventListener('click', (e) => {
        e.stopPropagation(); // Prevent folder load
        this.toggleSeriesSelection(folder);
      });

      // Click handler to load folder
      folderItem.addEventListener('click', () => {
        this.loadFolder(folder);
      });

      content.appendChild(folderItem);
    }

    console.log('[DICOM Viewer] ✅ Folder browser populated with', visibleFolders.length, 'visible folders');
  }

  /**
   * Check if a folder has children
   */
  hasChildren(folder) {
    return this.folders.some(f =>
      f.depth === folder.depth + 1 &&
      f.folderPath.length === folder.folderPath.length + 1 &&
      f.folderPath[folder.folderPath.length] === folder.folderName.trimStart()
    );
  }

  /**
   * Get direct child folders of a folder
   */
  getChildFolders(folder) {
    return this.folders.filter(f =>
      f.depth === folder.depth + 1 &&
      f.folderPath.length === folder.folderPath.length + 1 &&
      f.folderPath[folder.folderPath.length] === folder.folderName.trimStart()
    );
  }

  /**
   * Toggle folder collapse/expand state
   */
  toggleFolderCollapse(folderId) {
    if (this.collapsedFolders.has(folderId)) {
      this.collapsedFolders.delete(folderId);
      console.log('[DICOM Viewer] 📂 Expanded folder:', folderId);
    } else {
      this.collapsedFolders.add(folderId);
      console.log('[DICOM Viewer] 📁 Collapsed folder:', folderId);
    }
    // Re-render the folder browser
    this.populateFolderBrowser();
  }

  /**
   * Toggle series selection for analysis
   */
  toggleSeriesSelection(folder) {
    const existingIndex = this.selectedSeriesForAnalysis.findIndex(s => s.folderId === folder.folderId);

    if (existingIndex >= 0) {
      // Remove from selection
      const removed = this.selectedSeriesForAnalysis.splice(existingIndex, 1)[0];
      console.log('[DICOM Viewer] Removed series from analysis:', folder.folderName, '- Had', removed.docIds ? removed.docIds.length : 0, 'images');
    } else {
      // Add to selection
      console.log('[DICOM Viewer] Adding series - folder.files:', folder.files ? folder.files.length : 0);

      const docIds = folder.files
        .filter(f => f && f.docId)
        .map(f => f.docId);

      console.log('[DICOM Viewer] Extracted docIds:', docIds.length, '- First 3:', docIds.slice(0, 3));

      this.selectedSeriesForAnalysis.push({
        folderId: folder.folderId,
        folderName: folder.folderName.trimStart(),
        docIds: docIds,
        folder: folder // Store full folder object for metadata
      });
      console.log('[DICOM Viewer] Added series to analysis:', folder.folderName, '- Images:', docIds.length);
      console.log('[DICOM Viewer] Current selectedSeriesForAnalysis:', this.selectedSeriesForAnalysis.map(s => `${s.folderName} (${s.docIds.length} images)`));
    }

    // Update UI
    this.populateFolderBrowser(); // Re-render to update checkboxes
    this.updateSelectedSeriesList(); // Update analysis panel
  }

  /**
   * Clear all series selections
   */
  clearAllSeriesSelection() {
    this.selectedSeriesForAnalysis = [];
    console.log('[DICOM Viewer] Cleared all series selections');
    this.populateFolderBrowser(); // Re-render to update checkboxes
    this.updateSelectedSeriesList(); // Update analysis panel
  }

  /**
   * Select all available series
   */
  selectAllSeries() {
    this.selectedSeriesForAnalysis = [];

    for (const folder of this.folders) {
      if (folder.files && folder.files.length > 0) {
        const docIds = folder.files
          .filter(f => f && f.docId)
          .map(f => f.docId);

        if (docIds.length > 0) {
          this.selectedSeriesForAnalysis.push({
            folderId: folder.folderId,
            folderName: folder.folderName.trimStart(),
            docIds: docIds,
            folder: folder
          });
        }
      }
    }

    console.log('[DICOM Viewer] Selected all series:', this.selectedSeriesForAnalysis.length);
    this.populateFolderBrowser(); // Re-render to update checkboxes
    this.updateSelectedSeriesList(); // Update analysis panel
  }

  /**
   * Update the selected series list in the analysis panel
   */
  updateSelectedSeriesList() {
    const listEl = document.getElementById('selected-series-list');
    const buttonEl = document.getElementById('run-analysis-button');

    // Elements may not exist if analysis panel isn't open yet
    if (!listEl || !buttonEl) {
      console.log('[DICOM Viewer] Analysis panel not visible, skipping series list update');
      return;
    }

    if (this.selectedSeriesForAnalysis.length === 0) {
      listEl.innerHTML = '<div style="color: #666; font-style: italic;">No series selected</div>';
      buttonEl.disabled = true;
      buttonEl.style.opacity = '0.5';
      buttonEl.style.cursor = 'not-allowed';
    } else {
      const totalImages = this.selectedSeriesForAnalysis.reduce((sum, s) => sum + s.docIds.length, 0);

      let html = '';
      for (const series of this.selectedSeriesForAnalysis) {
        html += `
          <div style="display: flex; align-items: center; justify-content: space-between; padding: 6px 8px; margin-bottom: 4px; background: #1f1f1f; border-radius: 4px;">
            <div style="flex: 1;">
              <div style="font-weight: 500; color: #fff;">${this.escapeHtml(series.folderName)}</div>
              <div style="font-size: 10px; color: #888;">${series.docIds.length} images</div>
            </div>
            <div class="remove-series-btn" data-folder-id="${series.folderId}" style="color: #ff6b6b; cursor: pointer; padding: 4px 8px; font-size: 14px; font-weight: bold;" title="Remove from analysis">✕</div>
          </div>
        `;
      }

      html += `
        <div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid #333; font-size: 11px; color: #0066cc; font-weight: 600;">
          Total: ${this.selectedSeriesForAnalysis.length} series, ${totalImages} images
        </div>
      `;

      listEl.innerHTML = html;
      buttonEl.disabled = false;
      buttonEl.style.opacity = '1';
      buttonEl.style.cursor = 'pointer';

      // Add click handlers for remove buttons
      listEl.querySelectorAll('.remove-series-btn').forEach(btn => {
        btn.addEventListener('click', (e) => {
          const folderId = parseInt(e.target.dataset.folderId);
          const folder = this.folders.find(f => f.folderId === folderId);
          if (folder) {
            this.toggleSeriesSelection(folder);
          }
        });
      });
    }
  }

  /**
   * Load a folder as a DICOM series
   */
  async loadFolder(folder) {
    try {
      console.log('[DICOM Viewer] Loading folder:', folder.folderName);

      if (!this.viewportManager) {
        throw new Error('ViewportManager not initialized');
      }

      // Update active folder in UI
      document.querySelectorAll('.folder-item').forEach(item => {
        item.classList.remove('active');
      });

      const clickedItem = Array.from(document.querySelectorAll('.folder-item'))
        .find(item => item.dataset.folderId === folder.folderName);

      if (clickedItem) {
        clickedItem.classList.add('active');
      }

      this.currentFolderId = folder.folderName;
      this.currentFolder = folder; // Store full folder object with file metadata

      // Extract docIds from folder files
      console.log('[DICOM Viewer] Folder files:', folder.files);

      // Filter out any files without docIds
      const docIds = folder.files
        .filter(f => f && f.docId)
        .map(f => f.docId);

      console.log('[DICOM Viewer] Loading', docIds.length, 'images into active viewport');

      if (docIds.length === 0) {
        throw new Error('No valid files with docIds found in folder');
      }

      // Load series into active viewport
      await this.viewportManager.loadSeriesIntoActiveViewport(
        folder.folderId || folder.folderName,
        docIds,
        folder
      );

      // Update series UI
      this.updateSeriesControls();

      // Generate thumbnails (TODO: update for multi-viewport)
      // For now, skip thumbnails as they're tied to single viewport
      // await this.generateThumbnails();

      // Auto-select this series for analysis if not already selected
      const isAlreadySelected = this.selectedSeriesForAnalysis.some(s => s.folderId === folder.folderId);
      if (!isAlreadySelected) {
        this.toggleSeriesSelection(folder);
        console.log('[DICOM Viewer] Series loaded and auto-selected for analysis');
      } else {
        console.log('[DICOM Viewer] Series loaded - already selected for analysis');
      }

    } catch (error) {
      console.error('[DICOM Viewer] Failed to load folder:', error);
      this.showError('Failed to load folder: ' + error.message);
    }
  }

  /**
   * Toggle folder browser visibility
   */
  toggleFolderBrowser() {
    const browser = document.getElementById('folder-browser');
    const viewerContainer = document.getElementById('viewer-container');
    const thumbnailStrip = document.getElementById('thumbnail-strip');

    browser.classList.toggle('collapsed');

    const isCollapsed = browser.classList.contains('collapsed');

    if (isCollapsed) {
      viewerContainer.classList.remove('with-sidebar');
      thumbnailStrip.classList.remove('with-sidebar');
    } else {
      viewerContainer.classList.add('with-sidebar');
      thumbnailStrip.classList.add('with-sidebar');
    }
  }

  download() {
    if (this.fileUrl) {
      const a = document.createElement('a');
      a.href = this.fileUrl;
      a.download = 'dicom-image.dcm';
      a.click();
    }
  }

  escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  /**
   * Toggle analysis panel visibility
   */
  toggleAnalysisPanel() {
    const panel = document.getElementById('analysis-panel');
    const viewerContainer = document.getElementById('viewer-container');
    const thumbnailStrip = document.getElementById('thumbnail-strip');

    panel.classList.toggle('collapsed');

    const isCollapsed = panel.classList.contains('collapsed');

    if (isCollapsed) {
      viewerContainer.classList.remove('with-analysis');
      thumbnailStrip.classList.remove('with-analysis');
    } else {
      viewerContainer.classList.add('with-analysis');
      thumbnailStrip.classList.add('with-analysis');
    }
  }

  /**
   * Start analysis for the selected series
   */
  async startAnalysis() {
    if (this.analysisRunning) {
      console.log('[DICOM Viewer] Analysis already running');
      return;
    }

    if (!this.selectedSeriesForAnalysis || this.selectedSeriesForAnalysis.length === 0) {
      console.log('[DICOM Viewer] No series selected for analysis');
      return;
    }

    // Preserve folder structure for analysis
    const folderGroups = [];
    let totalImages = 0;

    for (const series of this.selectedSeriesForAnalysis) {
      console.log('[DICOM Viewer] Adding series:', series.folderName, '- DocIds:', series.docIds ? series.docIds.length : 0);
      if (series.docIds && series.docIds.length > 0) {
        folderGroups.push({
          folderName: series.folderName,
          docIds: series.docIds
        });
        totalImages += series.docIds.length;
      } else {
        console.warn('[DICOM Viewer] WARNING: Series has no docIds:', series);
      }
    }

    const seriesCount = folderGroups.length;
    const seriesNames = folderGroups.map(s => s.folderName).join(', ');

    console.log('[DICOM Viewer] Starting analysis for', seriesCount, 'folder groups:', seriesNames);
    console.log('[DICOM Viewer] Total images to analyze:', totalImages);
    console.log('[DICOM Viewer] Folder groups:', folderGroups);

    this.analysisRunning = true;

    // Show analysis panel and toggle button
    document.getElementById('analysis-toggle').style.display = 'flex';
    document.getElementById('analysis-toggle').classList.add('analyzing');
    document.getElementById('analysis-panel').classList.remove('collapsed');
    document.getElementById('viewer-container').classList.add('with-analysis');
    document.getElementById('thumbnail-strip').classList.add('with-analysis');

    // Show progress state
    this.showAnalysisProgress();

    try {
      // Import the analyzer module dynamically
      const { analyzeRadiologyStudy } = await import('./radiology-analyzer.js');

      // Get user-provided case context
      const caseContextInput = document.getElementById('case-context-input');
      const userContext = caseContextInput ? caseContextInput.value.trim() : '';

      let caseContext = `Analysis of ${seriesCount} series: ${seriesNames}`;
      if (userContext) {
        caseContext += `\n\nAdditional Context from User:\n${userContext}`;
      }

      // Run analysis with folder groups preserved
      const result = await analyzeRadiologyStudy({
        folderGroups: folderGroups,
        projectId: this.projectId, // Pass projectId for on-demand file downloads
        caseContext: caseContext,
        onProgress: (progress) => this.updateAnalysisProgress(progress),
        onStatus: (status) => this.updateAnalysisStatus(status)
      });

      console.log('[DICOM Viewer] Analysis complete:', result);

      if (result.success) {
        this.currentAnalysis = result;
        this.displayAnalysisResults(result);
      } else {
        this.showAnalysisError(result.error);
      }

    } catch (error) {
      console.error('[DICOM Viewer] Analysis failed:', error);
      this.showAnalysisError(error.message);
    } finally {
      this.analysisRunning = false;
      document.getElementById('analysis-toggle').classList.remove('analyzing');
    }
  }

  /**
   * Show analysis progress state
   */
  showAnalysisProgress() {
    const content = document.getElementById('analysis-panel-content');
    content.innerHTML = `
      <div class="analysis-state">
        <div class="analysis-state-icon">⚙️</div>
        <div class="analysis-state-title">Analyzing Images...</div>
        <div class="analysis-state-message" id="analysis-status-message">
          Initializing analysis...
        </div>
        <div class="analysis-progress">
          <div class="analysis-progress-bar">
            <div class="analysis-progress-fill" id="analysis-progress-fill" style="width: 0%"></div>
          </div>
          <div class="analysis-cost-estimate" id="analysis-cost-estimate"></div>
        </div>
      </div>
    `;
  }

  /**
   * Update analysis progress
   */
  updateAnalysisProgress(progress) {
    const fill = document.getElementById('analysis-progress-fill');
    if (fill) {
      fill.style.width = `${progress}%`;
    }
  }

  /**
   * Update analysis status message
   */
  updateAnalysisStatus(status) {
    const message = document.getElementById('analysis-status-message');
    if (message) {
      message.textContent = status;
    }

    // Extract cost estimate from status if present
    if (status.includes('$')) {
      const costEstimate = document.getElementById('analysis-cost-estimate');
      if (costEstimate) {
        costEstimate.textContent = status;
      }
    }
  }

  /**
   * Display analysis results
   */
  displayAnalysisResults(result) {
    const { analysis, study, usage, timestamp } = result;

    if (analysis.parse_error) {
      this.showAnalysisError(analysis.parse_error);
      return;
    }

    const content = document.getElementById('analysis-panel-content');

    // Build results HTML
    let html = '<div class="analysis-results">';

    // Export Button
    html += `
      <div style="margin-bottom: 16px;">
        <button id="export-pdf-button" style="width: 100%; padding: 10px 20px; background: #16a34a; color: white; border: none; border-radius: 4px; font-size: 13px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;">
          <span>📄</span> Export PDF
        </button>
      </div>
    `;

    // Study Summary
    if (analysis.study_summary) {
      html += this.buildAnalysisSection('Study Summary', `
        ${this.buildField('Body Part', analysis.study_summary.body_part)}
        ${this.buildField('Modality', analysis.study_summary.modality)}
        ${this.buildField('Study Type', analysis.study_summary.study_type)}
        ${this.buildField('Image Quality', analysis.study_summary.image_quality)}
        ${analysis.study_summary.quality_notes ? this.buildField('Quality Notes', analysis.study_summary.quality_notes) : ''}
        ${this.buildField('Images Analyzed', `${analysis.study_summary.total_images_analyzed} images across ${analysis.study_summary.series_count} series`)}
      `, true);
    }

    // Critical Findings (if present) - Show this prominently
    if (analysis.critical_findings) {
      let criticalHtml = '';

      if (analysis.critical_findings.structures_not_clearly_visualized?.length) {
        criticalHtml += '<div style="margin-bottom: 16px;"><div style="font-weight: 600; color: #ff6b6b; margin-bottom: 8px;">⚠️ Structures Not Clearly Visualized:</div>';
        for (const item of analysis.critical_findings.structures_not_clearly_visualized) {
          criticalHtml += `
            <div style="margin-bottom: 12px; padding: 10px; background: rgba(255, 107, 107, 0.1); border-left: 3px solid #ff6b6b; border-radius: 4px;">
              <div style="font-weight: 600; margin-bottom: 4px;">${this.escapeHtml(item.structure)}</div>
              <div style="font-size: 11px; color: #ccc; margin-bottom: 4px;"><strong>Clinical Significance:</strong> ${this.escapeHtml(item.clinical_significance)}</div>
              <div style="font-size: 11px; color: #ccc; margin-bottom: 4px;"><strong>Expected Visibility:</strong> ${this.escapeHtml(item.expected_visibility)}</div>
              ${item.possible_explanations?.length ? `<div style="font-size: 11px; color: #ccc;"><strong>Possible Explanations:</strong> ${item.possible_explanations.map(e => this.escapeHtml(e)).join('; ')}</div>` : ''}
            </div>
          `;
        }
        criticalHtml += '</div>';
      }

      if (analysis.critical_findings.secondary_signs_identified?.length) {
        criticalHtml += '<div style="margin-bottom: 16px;"><div style="font-weight: 600; color: #fbbf24; margin-bottom: 8px;">🔍 Secondary Signs Identified:</div>';
        for (const sign of analysis.critical_findings.secondary_signs_identified) {
          criticalHtml += `
            <div style="margin-bottom: 8px; padding: 8px; background: rgba(251, 191, 36, 0.1); border-left: 3px solid #fbbf24; border-radius: 4px;">
              <div style="font-size: 11px; color: #ccc;"><strong>${this.escapeHtml(sign.finding)}</strong> at ${this.escapeHtml(sign.location)}</div>
              <div style="font-size: 11px; color: #888;">Suggests: ${this.escapeHtml(sign.suggests)}</div>
            </div>
          `;
        }
        criticalHtml += '</div>';
      }

      if (criticalHtml) {
        html += this.buildAnalysisSection('🚨 Critical Findings', criticalHtml, true);
      }
    }

    // Overall Impression
    if (analysis.overall_impression) {
      html += this.buildAnalysisSection('Overall Impression', `
        ${this.buildField('Summary', analysis.overall_impression.summary)}
        ${this.buildList('Key Findings', analysis.overall_impression.key_findings)}
        ${this.buildList('Limitations', analysis.overall_impression.limitations)}
        ${analysis.overall_impression.recommendations?.length ? this.buildList('Recommendations', analysis.overall_impression.recommendations) : ''}
      `, true);
    }

    // Findings
    if (analysis.findings) {
      let findingsHtml = '';
      if (analysis.findings.primary_observations?.length) {
        findingsHtml += this.buildList('Primary Observations', analysis.findings.primary_observations);
      }
      if (analysis.findings.secondary_observations?.length) {
        findingsHtml += this.buildList('Secondary Observations', analysis.findings.secondary_observations);
      }
      if (analysis.findings.normal_findings?.length) {
        findingsHtml += this.buildList('Normal Findings', analysis.findings.normal_findings);
      }
      if (analysis.findings.indeterminate?.length) {
        findingsHtml += this.buildList('Indeterminate', analysis.findings.indeterminate);
      }
      if (findingsHtml) {
        html += this.buildAnalysisSection('Detailed Findings', findingsHtml);
      }
    }

    // Series Analysis
    if (analysis.series_analysis?.length) {
      let seriesHtml = '';
      for (const series of analysis.series_analysis) {
        seriesHtml += `
          <div class="analysis-field" style="margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #333;">
            <div style="font-weight: 600; color: #0066cc; margin-bottom: 8px;">${this.escapeHtml(series.series_name)}</div>
            ${this.buildField('Sequence Type', series.sequence_type)}
            ${this.buildField('Plane', series.plane)}
            ${this.buildField('Slices', series.slice_count)}
            ${series.what_this_sequence_shows ? this.buildField('What This Shows', series.what_this_sequence_shows) : ''}
            ${series.observations ? this.buildField('Observations', series.observations) : ''}
            ${series.signal_characteristics ? this.buildField('Signal Characteristics', series.signal_characteristics) : ''}
            ${series.structures_visualized?.length ? this.buildList('Structures Visualized', series.structures_visualized) : ''}
            ${series.areas_of_note?.length ? this.buildList('Areas of Note', series.areas_of_note) : ''}
          </div>
        `;
      }
      html += this.buildAnalysisSection('Series Analysis', seriesHtml);
    }

    // Anatomical Assessment
    if (analysis.anatomical_assessment?.structures_evaluated) {
      let structuresHtml = '';
      for (const [structureName, assessment] of Object.entries(analysis.anatomical_assessment.structures_evaluated)) {
        const badgeClass = assessment.appearance.toLowerCase();

        // Color code based on visualization status
        let vizStatusColor = '#4ade80'; // green for clearly visualized
        if (assessment.visualization_status?.includes('Not Clearly')) {
          vizStatusColor = '#ff6b6b'; // red
        } else if (assessment.visualization_status?.includes('Partially')) {
          vizStatusColor = '#fbbf24'; // yellow
        } else if (assessment.visualization_status?.includes('Cannot Assess')) {
          vizStatusColor = '#888'; // gray
        }

        // Color code concern level
        let concernBadge = '';
        if (assessment.concern_level) {
          const concernColors = {
            'None': '#4ade80',
            'Low': '#a3e635',
            'Moderate': '#fbbf24',
            'High': '#fb923c',
            'Critical': '#ff6b6b'
          };
          const concernColor = concernColors[assessment.concern_level] || '#888';
          concernBadge = `<span style="background: ${concernColor}20; color: ${concernColor}; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: 600; margin-left: 8px;">${assessment.concern_level}</span>`;
        }

        structuresHtml += `
          <div class="analysis-field" style="margin-bottom: 16px; padding: 12px; background: #1f1f1f; border-radius: 6px;">
            <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
              <strong style="font-size: 13px;">${this.escapeHtml(structureName)}</strong>
              <div>
                <span class="analysis-badge ${badgeClass}">${assessment.appearance}</span>
                ${concernBadge}
              </div>
            </div>

            ${assessment.visualization_status ? `
              <div style="margin-bottom: 8px; padding: 6px; background: ${vizStatusColor}15; border-left: 3px solid ${vizStatusColor}; border-radius: 3px;">
                <div style="font-size: 10px; color: ${vizStatusColor}; font-weight: 600; text-transform: uppercase;">Visualization</div>
                <div style="font-size: 11px; color: #ccc;">${this.escapeHtml(assessment.visualization_status)}</div>
              </div>
            ` : ''}

            ${assessment.expected_normal_appearance ? `
              <div style="margin-bottom: 6px;">
                <div style="font-size: 10px; color: #888; text-transform: uppercase; margin-bottom: 2px;">Expected Normal</div>
                <div style="font-size: 11px; color: #ccc;">${this.escapeHtml(assessment.expected_normal_appearance)}</div>
              </div>
            ` : ''}

            ${assessment.observed_appearance ? `
              <div style="margin-bottom: 6px;">
                <div style="font-size: 10px; color: #888; text-transform: uppercase; margin-bottom: 2px;">Observed</div>
                <div style="font-size: 11px; color: #fff;">${this.escapeHtml(assessment.observed_appearance)}</div>
              </div>
            ` : ''}

            ${assessment.description ? `
              <div style="margin-bottom: 6px; color: #ccc; font-size: 11px; line-height: 1.5;">${this.escapeHtml(assessment.description)}</div>
            ` : ''}

            ${assessment.internal_comparison ? `
              <div style="margin-bottom: 6px; padding: 6px; background: #0066cc15; border-left: 2px solid #0066cc; border-radius: 3px;">
                <div style="font-size: 10px; color: #0066cc; font-weight: 600; margin-bottom: 2px;">INTERNAL COMPARISON</div>
                <div style="font-size: 11px; color: #ccc;">${this.escapeHtml(assessment.internal_comparison)}</div>
              </div>
            ` : ''}

            ${assessment.secondary_signs_checked?.length ? `
              <div style="margin-top: 8px;">
                <div style="font-size: 10px; color: #888; text-transform: uppercase; margin-bottom: 4px;">Secondary Signs Checked</div>
                <div style="font-size: 11px; color: #888;">${assessment.secondary_signs_checked.map(s => this.escapeHtml(s)).join(', ')}</div>
              </div>
            ` : ''}

            <div style="margin-top: 6px; display: flex; justify-content: space-between; font-size: 10px; color: #666;">
              <span>Confidence: ${assessment.confidence}</span>
            </div>
          </div>
        `;
      }
      html += this.buildAnalysisSection('Detailed Anatomical Assessment', structuresHtml);
    }

    // Litigation Relevance
    if (analysis.litigation_relevance) {
      html += this.buildAnalysisSection('Litigation Relevance', `
        ${analysis.litigation_relevance.structures_commonly_relevant_to_injury?.length ?
          this.buildList('Injury-Relevant Structures', analysis.litigation_relevance.structures_commonly_relevant_to_injury) : ''}
        ${analysis.litigation_relevance.objective_findings_summary ?
          this.buildField('Objective Findings Summary', analysis.litigation_relevance.objective_findings_summary) : ''}
        ${analysis.litigation_relevance.questions_for_radiologist?.length ?
          this.buildList('Questions for Radiologist', analysis.litigation_relevance.questions_for_radiologist) : ''}
        ${analysis.litigation_relevance.questions_for_treating_physician?.length ?
          this.buildList('Questions for Physician', analysis.litigation_relevance.questions_for_treating_physician) : ''}
      `);
    }

    // Usage Stats
    if (usage) {
      html += `
        <div style="margin-top: 16px; padding: 12px; background: #252525; border-radius: 6px; font-size: 11px; color: #888;">
          <div><strong>Analysis Cost:</strong> ~$${usage.estimatedCost}</div>
          <div><strong>Tokens:</strong> ${usage.inputTokens?.toLocaleString() || 'N/A'} input / ${usage.outputTokens?.toLocaleString() || 'N/A'} output</div>
          <div><strong>Completed:</strong> ${new Date(timestamp).toLocaleString()}</div>
        </div>
      `;
    }

    html += '</div>';

    content.innerHTML = html;

    // Add click handlers for collapsible sections
    content.querySelectorAll('.analysis-section-header').forEach(header => {
      header.addEventListener('click', () => {
        header.parentElement.classList.toggle('expanded');
      });
    });

    // Add PDF export button handler
    const exportBtn = document.getElementById('export-pdf-button');
    if (exportBtn) {
      exportBtn.addEventListener('click', async () => {
        const { exportAnalysisToPDF } = await import('./pdf-export.js');
        exportAnalysisToPDF(result);
      });
    }

    // Upload functionality temporarily removed - requires Filevine Public API implementation
    // TODO: Implement upload using Filevine Public API with proper authentication
  }

  /**
   * Export analysis to PDF (deprecated - using pdf-export.js module)
   */
  async exportAnalysisToPDF_OLD(result) {
    try {
      const { analysis, study, usage, timestamp } = result;

      // Create a formatted text document
      let text = '╔══════════════════════════════════════════════════════════╗\n';
      text += '║          AI RADIOLOGY ANALYSIS REPORT                   ║\n';
      text += '╚══════════════════════════════════════════════════════════╝\n\n';

      // Study Summary
      if (analysis.study_summary) {
        text += 'STUDY SUMMARY\n';
        text += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
        text += `Body Part: ${analysis.study_summary.body_part}\n`;
        text += `Modality: ${analysis.study_summary.modality}\n`;
        text += `Study Type: ${analysis.study_summary.study_type}\n`;
        text += `Image Quality: ${analysis.study_summary.image_quality}\n`;
        if (analysis.study_summary.quality_notes) {
          text += `Quality Notes: ${analysis.study_summary.quality_notes}\n`;
        }
        text += `Images Analyzed: ${analysis.study_summary.total_images_analyzed} images across ${analysis.study_summary.series_count} series\n\n`;
      }

      // Critical Findings
      if (analysis.critical_findings) {
        text += 'CRITICAL FINDINGS\n';
        text += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';

        if (analysis.critical_findings.structures_not_clearly_visualized?.length) {
          text += '\n⚠️  STRUCTURES NOT CLEARLY VISUALIZED:\n\n';
          for (const item of analysis.critical_findings.structures_not_clearly_visualized) {
            text += `• ${item.structure}\n`;
            text += `  Clinical Significance: ${item.clinical_significance}\n`;
            text += `  Expected Visibility: ${item.expected_visibility}\n`;
            if (item.possible_explanations?.length) {
              text += `  Possible Explanations: ${item.possible_explanations.join('; ')}\n`;
            }
            text += '\n';
          }
        }

        if (analysis.critical_findings.secondary_signs_identified?.length) {
          text += '\n🔍 SECONDARY SIGNS IDENTIFIED:\n\n';
          for (const sign of analysis.critical_findings.secondary_signs_identified) {
            text += `• ${sign.finding} at ${sign.location}\n`;
            text += `  Suggests: ${sign.suggests}\n\n`;
          }
        }
      }

      // Overall Impression
      if (analysis.overall_impression) {
        text += '\nOVERALL IMPRESSION\n';
        text += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
        if (analysis.overall_impression.summary) {
          text += `${analysis.overall_impression.summary}\n\n`;
        }
        if (analysis.overall_impression.key_findings?.length) {
          text += 'Key Findings:\n';
          for (const finding of analysis.overall_impression.key_findings) {
            text += `• ${finding}\n`;
          }
          text += '\n';
        }
      }

      // Findings
      if (analysis.findings) {
        text += '\nDETAILED FINDINGS\n';
        text += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';

        if (analysis.findings.primary_observations?.length) {
          text += '\nPrimary Observations:\n';
          for (const obs of analysis.findings.primary_observations) {
            text += `• ${obs}\n`;
          }
          text += '\n';
        }

        if (analysis.findings.secondary_observations?.length) {
          text += '\nSecondary Observations:\n';
          for (const obs of analysis.findings.secondary_observations) {
            text += `• ${obs}\n`;
          }
          text += '\n';
        }

        if (analysis.findings.normal_findings?.length) {
          text += '\nNormal Findings:\n';
          for (const obs of analysis.findings.normal_findings) {
            text += `• ${obs}\n`;
          }
          text += '\n';
        }
      }

      // Litigation Relevance
      if (analysis.litigation_relevance) {
        text += '\nLITIGATION RELEVANCE\n';
        text += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
        if (analysis.litigation_relevance.objective_findings_summary) {
          text += `${analysis.litigation_relevance.objective_findings_summary}\n\n`;
        }
        if (analysis.litigation_relevance.questions_for_radiologist?.length) {
          text += '\nQuestions for Radiologist:\n';
          for (const q of analysis.litigation_relevance.questions_for_radiologist) {
            text += `• ${q}\n`;
          }
        }
      }

      // Metadata
      text += '\n\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
      text += 'ANALYSIS METADATA\n';
      text += `Date: ${new Date(timestamp).toLocaleString()}\n`;
      if (usage) {
        text += `Estimated Cost: $${usage.estimatedCost}\n`;
        text += `Tokens: ${usage.inputTokens?.toLocaleString() || 'N/A'} input / ${usage.outputTokens?.toLocaleString() || 'N/A'} output\n`;
      }
      text += '\n🤖 Generated by Claude Sonnet 4.5 via Filevine DICOM Viewer\n';
      text += 'Note: This is an AI-assisted analysis for legal review purposes.\n';
      text += 'NOT A MEDICAL DIAGNOSIS. Consult qualified radiologist for interpretation.\n';

      // Create blob and download
      const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `radiology-analysis-${new Date().toISOString().split('T')[0]}.txt`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);

      console.log('[DICOM Viewer] Analysis exported as text file');
    } catch (error) {
      console.error('[DICOM Viewer] Failed to export PDF:', error);
      alert('Failed to export analysis: ' + error.message);
    }
  }

  /**
   * Upload analysis report to Filevine
   * TEMPORARILY DISABLED - Requires Filevine Public API implementation
   * TODO: Implement using Filevine Public API for proper S3 upload authentication
   */
  /* async uploadAnalysisToFilevine(result) {
    try {
      console.log('[DICOM Viewer] Starting upload to Filevine');

      // Check if we have a project ID
      if (!this.projectId) {
        alert('Cannot upload: No project ID available. Please open the viewer from a Filevine project.');
        return;
      }

      // Update button to show loading state
      const uploadBtn = document.getElementById('upload-to-filevine-button');
      if (uploadBtn) {
        uploadBtn.disabled = true;
        uploadBtn.innerHTML = '<span>⏳</span> Uploading...';
      }

      // Generate HTML report
      const { generateHtmlReport, generateReportFilename } = await import('./report-generator.js');
      const htmlContent = generateHtmlReport(result);
      const filename = generateReportFilename(result.study);

      console.log('[DICOM Viewer] Generated report:', filename);

      // Convert HTML to Blob
      const blob = new Blob([htmlContent], { type: 'text/html;charset=utf-8' });

      // Convert Blob to data URL for message passing
      const reader = new FileReader();
      const dataUrl = await new Promise((resolve, reject) => {
        reader.onloadend = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(blob);
      });

      console.log('[DICOM Viewer] Uploading to Filevine project:', this.projectId);

      // Send upload request to background script
      const response = await chrome.runtime.sendMessage({
        type: 'UPLOAD_DOCUMENT_TO_FILEVINE',
        dataUrl,
        filename,
        projectId: this.projectId,
        folderId: null // Upload to root folder (could be made configurable)
      });

      if (response && response.success) {
        console.log('[DICOM Viewer] Upload successful, docId:', response.docId);

        // Update button to show success
        if (uploadBtn) {
          uploadBtn.innerHTML = '<span>✅</span> Uploaded Successfully';
          uploadBtn.style.background = '#16a34a';

          // Reset button after 3 seconds
          setTimeout(() => {
            uploadBtn.disabled = false;
            uploadBtn.innerHTML = '<span>📤</span> Upload to Filevine';
            uploadBtn.style.background = '#2563eb';
          }, 3000);
        }

        alert(`Analysis report uploaded successfully to Filevine!\n\nDocument ID: ${response.docId}\nFilename: ${filename}`);
      } else {
        throw new Error(response?.error || 'Upload failed');
      }

    } catch (error) {
      console.error('[DICOM Viewer] Failed to upload to Filevine:', error);

      // Reset button to show error
      const uploadBtn = document.getElementById('upload-to-filevine-button');
      if (uploadBtn) {
        uploadBtn.disabled = false;
        uploadBtn.innerHTML = '<span>❌</span> Upload Failed';
        uploadBtn.style.background = '#dc2626';

        // Reset button after 3 seconds
        setTimeout(() => {
          uploadBtn.innerHTML = '<span>📤</span> Upload to Filevine';
          uploadBtn.style.background = '#2563eb';
        }, 3000);
      }

      alert('Failed to upload analysis to Filevine:\n\n' + error.message);
    }
  } */

  /**
   * Test upload with a simple text file
   * TEMPORARILY DISABLED - Requires Filevine Public API implementation
   */
  /* async testUploadToFilevine() {
    try {
      console.log('[DICOM Viewer] Starting test upload');

      // Check if we have a project ID
      if (!this.projectId) {
        alert('Cannot upload: No project ID available. Please open the viewer from a Filevine project.');
        return;
      }

      // Update button to show loading state (try both possible button IDs)
      const testBtn = document.getElementById('test-upload-header-btn') || document.getElementById('test-upload-button');
      if (testBtn) {
        testBtn.disabled = true;
        testBtn.innerHTML = '<span>⏳</span> Testing...';
      }

      // Create simple test file
      const content = `Test Upload Report
Generated: ${new Date().toISOString()}

This is a test upload from the Filevine DICOM Viewer extension.

Test Content:
- Line 1
- Line 2
- Line 3

End of test file.`;

      const filename = `test-upload-${Date.now()}.txt`;
      const blob = new Blob([content], { type: 'text/plain' });

      // Convert Blob to data URL
      const reader = new FileReader();
      const dataUrl = await new Promise((resolve, reject) => {
        reader.onloadend = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(blob);
      });

      console.log('[DICOM Viewer] Uploading test file to project:', this.projectId);
      console.log('[DICOM Viewer] Data URL length:', dataUrl?.length || 0);
      console.log('[DICOM Viewer] Data URL prefix:', dataUrl?.substring(0, 50) || 'undefined');

      // Send upload request to background script
      // Note: background handler extracts type and spreads rest into payload
      const response = await chrome.runtime.sendMessage({
        type: 'UPLOAD_DOCUMENT_TO_FILEVINE',
        dataUrl,
        filename,
        projectId: this.projectId,
        folderId: null
      });

      console.log('[DICOM Viewer] Upload response:', response);

      if (response && response.success) {
        console.log('[DICOM Viewer] Test upload successful, docId:', response.docId);

        // Update button to show success
        if (testBtn) {
          testBtn.innerHTML = '<span>✅</span> Test Success';
          testBtn.style.background = '#16a34a';

          setTimeout(() => {
            testBtn.disabled = false;
            testBtn.innerHTML = '<span>🧪</span> Test Upload';
            testBtn.style.background = '#9333ea';
          }, 3000);
        }

        alert(`Test file uploaded successfully!\n\nDocument ID: ${response.docId}\nFilename: ${filename}`);
      } else {
        throw new Error(response?.error || 'Upload failed');
      }

    } catch (error) {
      console.error('[DICOM Viewer] Test upload failed:', error);

      // Reset button to show error (try both possible button IDs)
      const testBtn = document.getElementById('test-upload-header-btn') || document.getElementById('test-upload-button');
      if (testBtn) {
        testBtn.disabled = false;
        testBtn.innerHTML = '<span>❌</span> Test Failed';
        testBtn.style.background = '#dc2626';

        setTimeout(() => {
          testBtn.innerHTML = '<span>🧪</span> Test Upload';
          testBtn.style.background = '#9333ea';
        }, 3000);
      }

      alert('Test upload failed:\n\n' + error.message);
    }
  } */

  /**
   * Build an analysis section (collapsible)
   */
  buildAnalysisSection(title, content, expanded = false) {
    return `
      <div class="analysis-section ${expanded ? 'expanded' : ''}">
        <div class="analysis-section-header">
          <div class="analysis-section-title">${this.escapeHtml(title)}</div>
          <div class="analysis-section-toggle"></div>
        </div>
        <div class="analysis-section-content">
          ${content}
        </div>
      </div>
    `;
  }

  /**
   * Build a field display
   */
  buildField(label, value) {
    return `
      <div class="analysis-field">
        <div class="analysis-field-label">${this.escapeHtml(label)}</div>
        <div class="analysis-field-value">${this.escapeHtml(value)}</div>
      </div>
    `;
  }

  /**
   * Build a list display
   */
  buildList(title, items) {
    if (!items || items.length === 0) return '';
    return `
      <div class="analysis-field">
        <div class="analysis-field-label">${this.escapeHtml(title)}</div>
        <ul class="analysis-list">
          ${items.map(item => `<li>${this.escapeHtml(item)}</li>`).join('')}
        </ul>
      </div>
    `;
  }

  /**
   * Show analysis error
   */
  showAnalysisError(errorMessage) {
    const content = document.getElementById('analysis-panel-content');
    content.innerHTML = `
      <div class="analysis-state">
        <div class="analysis-state-icon">❌</div>
        <div class="analysis-state-title">Analysis Failed</div>
        <div class="analysis-state-message">
          ${this.escapeHtml(errorMessage)}
        </div>
      </div>
    `;
  }
}

// Initialize viewer when DOM is ready
console.log('[DICOM Viewer] Script loaded, document.readyState:', document.readyState);

if (document.readyState === 'loading') {
  console.log('[DICOM Viewer] Waiting for DOMContentLoaded...');
  document.addEventListener('DOMContentLoaded', () => {
    console.log('[DICOM Viewer] DOMContentLoaded event fired, creating DicomViewer...');
    try {
      window.dicomViewer = new DicomViewer();
    } catch (error) {
      console.error('[DICOM Viewer] FATAL: Failed to create DicomViewer:', error);
      console.error('[DICOM Viewer] Error stack:', error.stack);
    }
  });
} else {
  console.log('[DICOM Viewer] DOM already loaded, creating DicomViewer immediately...');
  try {
    window.dicomViewer = new DicomViewer();
  } catch (error) {
    console.error('[DICOM Viewer] FATAL: Failed to create DicomViewer:', error);
    console.error('[DICOM Viewer] Error stack:', error.stack);
  }
}
