/**
 * Background Service Worker
 * 
 * Entry point for the extension's background process.
 * Handles all API calls, downloads, and state management.
 */

import { MESSAGE_TYPES, STORAGE_KEYS } from '../lib/constants.js';
import { authManager } from './auth.js';
import { filevineClient } from './api.js';
import { webApiClient } from './web-api-client.js';
import { downloadManager } from './downloads.js';
import { echomarkHandler } from './echomark-handler.js';
import { setupCookieInterceptor, getAllActiveSessions } from './cookie-interceptor-improved.js';
import { AIService } from './ai-service.js';
import { getFilevineUploadService } from './filevine-upload-service.js';

// Check if Side Panel API is available
function isSidePanelAvailable() {
  // Check multiple ways the API might be available
  if (typeof chrome === 'undefined') {
    console.log('[Filevine Plugin] chrome object not available');
    return false;
  }
  
  // Check if sidePanel exists
  if (chrome.sidePanel) {
    console.log('[Filevine Plugin] chrome.sidePanel found');
    return true;
  }
  
  // Check if it's available via chrome.runtime
  if (chrome.runtime && chrome.runtime.getManifest) {
    const manifest = chrome.runtime.getManifest();
    console.log('[Filevine Plugin] Manifest side_panel:', manifest.side_panel);
  }
  
  console.log('[Filevine Plugin] chrome.sidePanel not found. Available chrome APIs:', Object.keys(chrome).filter(k => !k.startsWith('_')).join(', '));
  return false;
}

/**
 * Setup side panel (if available) or fall back to popup
 */
async function setupSidePanel() {
  console.log('[Filevine Plugin] Setting up side panel...');
  console.log('[Filevine Plugin] Chrome version check - typeof chrome:', typeof chrome);
  
  // Wait a bit for chrome APIs to be fully available (sometimes there's a timing issue)
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Check if sidePanel API is available
  // It should be available if manifest.json has "side_panel" key
  const hasSidePanel = typeof chrome !== 'undefined' && chrome.sidePanel;
  
  console.log('[Filevine Plugin] chrome.sidePanel available:', hasSidePanel);
  console.log('[Filevine Plugin] chrome object keys:', typeof chrome !== 'undefined' ? Object.keys(chrome).filter(k => !k.startsWith('_')).slice(0, 20).join(', ') : 'chrome undefined');
  
  if (hasSidePanel) {
    try {
      // Set panel behavior to open when action icon is clicked
      console.log('[Filevine Plugin] Setting panel behavior...');
      await chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
      console.log('[Filevine Plugin] ✅ Panel behavior set (opens on icon click)');
      
      // Register side panel path
      console.log('[Filevine Plugin] Setting side panel options...');
      await chrome.sidePanel.setOptions({
        path: 'src/sidebar/sidebar.html',
        enabled: true
      });
      console.log('[Filevine Plugin] ✅ Side panel registered successfully');
      
      // Disable popup when side panel is available
      try {
        await chrome.action.setPopup({ popup: '' });
        console.log('[Filevine Plugin] ✅ Popup disabled (using sidebar)');
      } catch (error) {
        console.warn('[Filevine Plugin] Could not disable popup:', error);
      }
      return true;
    } catch (error) {
      console.error('[Filevine Plugin] Failed to register side panel:', error);
      console.error('[Filevine Plugin] Error details:', error.message, error.stack);
      console.warn('[Filevine Plugin] Side Panel API error. Using popup fallback.');
      return false;
    }
  } else {
    console.warn('[Filevine Plugin] Side Panel API not available.');
    console.warn('[Filevine Plugin] This might mean:');
    console.warn('[Filevine Plugin] 1. Chrome version < 114 (but you said you\'re on 143)');
    console.warn('[Filevine Plugin] 2. Manifest side_panel key not recognized');
    console.warn('[Filevine Plugin] 3. Service worker timing issue');
    console.warn('[Filevine Plugin] Using popup fallback.');
    return false;
  }
}

// Initialize AI Service
const aiService = new AIService();

// Pre-configured Anthropic API key
const ANTHROPIC_API_KEY = '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';

// Initialize on extension load
chrome.runtime.onInstalled.addListener(async () => {
  console.log('[Filevine Plugin] Extension installed/updated');
  await setupSidePanel();
  await initialize();

  // Load or set API key
  const keyLoaded = await aiService.loadApiKey();
  if (!keyLoaded && ANTHROPIC_API_KEY) {
    console.log('[Filevine Plugin] Setting up Anthropic API key...');
    await aiService.saveApiKey(ANTHROPIC_API_KEY);
  }
});

// Setup side panel and initialize when service worker starts
(async () => {
  await setupSidePanel();
  await initialize();

  // Load or set API key
  const keyLoaded = await aiService.loadApiKey();
  if (!keyLoaded && ANTHROPIC_API_KEY) {
    console.log('[Filevine Plugin] Setting up Anthropic API key...');
    await aiService.saveApiKey(ANTHROPIC_API_KEY);
  }
})();

// Handle extension icon click - open side panel (if available) or let popup handle it
// Note: If setPanelBehavior({ openPanelOnActionClick: true }) is set, this won't fire
// because the side panel opens automatically. This is a fallback.
chrome.action.onClicked.addListener(async (tab) => {
  // This only fires if popup is disabled (empty string) AND setPanelBehavior wasn't used
  if (typeof chrome !== 'undefined' && chrome.sidePanel) {
    try {
      console.log('[Filevine Plugin] Extension icon clicked, opening side panel manually');
      await chrome.sidePanel.open({ tabId: tab.id });
    } catch (error) {
      console.error('[Filevine Plugin] Failed to open side panel:', error);
      // Re-enable popup as fallback
      try {
        await chrome.action.setPopup({ popup: 'src/popup/popup.html' });
        console.log('[Filevine Plugin] Re-enabled popup as fallback');
      } catch (e) {
        console.error('[Filevine Plugin] Could not re-enable popup:', e);
      }
    }
  } else {
    // Side panel not available, popup should open automatically (default_popup)
    console.log('[Filevine Plugin] Side panel not available, popup should open');
  }
});

async function initialize() {
  console.log('[Filevine Plugin] Initializing...');
  
  // Set up cookie interceptor for ASP.NET cookies
  setupCookieInterceptor();
  
  // Restore auth state from storage
  const auth = await authManager.initialize();
  
  if (auth) {
    console.log('[Filevine Plugin] Restored auth for user:', auth.userId);
    // Initialize web API client if using cookie-based auth
    if (auth.usingWebApi && auth.cookie) {
      webApiClient.setCredentials({
        cookie: auth.cookie,
        userId: auth.userId,
        orgId: auth.orgId
      });
      console.log('[Filevine Plugin] Web API client initialized');
    }
  } else {
    console.log('[Filevine Plugin] No stored auth, waiting for session detection');
  }

  // Initialize download manager DB
  await downloadManager.initializeDb();

  // Initialize Echomark handler DB
  await echomarkHandler.initializeDb();

  console.log('[Filevine Plugin] Initialization complete');
}

// Handle messages from content scripts and popup
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // Handle async responses
  handleMessage(message, sender)
    .then(sendResponse)
    .catch(error => {
      console.error('[Filevine Plugin] Message handler error:', error);
      sendResponse({ error: error.message });
    });
  
  // Return true to indicate async response
  return true;
});

/**
 * Main message handler
 */
async function handleMessage(message, sender) {
  const { type, ...payload } = message;
  
  switch (type) {
    // =====================================
    // Authentication
    // =====================================
    
    case MESSAGE_TYPES.AUTH_DETECTED:
      // Content script detected auth tokens
      console.log('[Filevine Plugin] Auth tokens received from content script');
      return authManager.processTokens(payload);
    
    case 'cookie_auth_success':
      // Cookie interceptor found that web app API accepts cookies
      console.log('[Filevine Plugin] Cookie auth successful, processing...');
      return authManager.processCookieAuth(payload);
    
    case MESSAGE_TYPES.GET_AUTH_STATE:
      return authManager.getState();
    
    case 'switch_org':
      return authManager.switchOrg(payload.orgId);
    
    case 'logout':
      await authManager.clearAuth();
      return { success: true };

    // =====================================
    // Multi-Session Management
    // =====================================

    case MESSAGE_TYPES.GET_ACTIVE_SESSIONS:
      // Get all active Filevine sessions across tabs
      const sessions = await getAllActiveSessions();
      return { success: true, sessions };

    case MESSAGE_TYPES.SWITCH_TO_SESSION:
      // Switch to a specific tab
      try {
        await chrome.tabs.update(payload.tabId, { active: true });
        // Also bring the window to front
        const tab = await chrome.tabs.get(payload.tabId);
        await chrome.windows.update(tab.windowId, { focused: true });
        return { success: true };
      } catch (error) {
        console.error('[Filevine Plugin] Failed to switch to session:', error);
        throw new Error(`Failed to switch to tab: ${error.message}`);
      }

    // =====================================
    // Projects
    // =====================================
    
    case MESSAGE_TYPES.GET_PROJECTS:
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      // Use web API client if using cookie-based auth
      const auth = authManager.getState();
      console.log('[Background] GET_PROJECTS request');
      console.log('[Background] Auth state:', JSON.stringify(auth).substring(0, 300));
      console.log('[Background] Payload:', JSON.stringify(payload));
      
      if (auth.auth?.usingWebApi) {
        console.log('[Background] Using web API client for projects');
        console.log('[Background] Web API client authenticated:', webApiClient.isAuthenticated());
        
        // Make sure web API client is initialized
        if (!webApiClient.isAuthenticated() && auth.auth.cookie) {
          console.log('[Background] Initializing web API client...');
          webApiClient.setCredentials({
            cookie: auth.auth.cookie,
            userId: auth.auth.userId,
            orgId: auth.auth.orgId
          });
        }
        
        try {
          const result = await webApiClient.getProjects(payload);
          console.log('[Background] Projects result:', result);
          return result;
        } catch (error) {
          console.error('[Background] Web API error:', error);
          throw error;
        }
      } else {
        console.log('[Background] Using external API client for projects');
        return filevineClient.getProjects(payload);
      }
    
    case 'get_project':
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      return filevineClient.getProject(payload.projectId);
    
    // =====================================
    // Documents
    // =====================================
    
    case MESSAGE_TYPES.GET_PROJECT_DOCS:
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      // Use web API client if using cookie-based auth
      const authState = authManager.getState();
      if (authState.auth?.usingWebApi) {
        return webApiClient.getProjectDocuments(payload.projectId, payload);
      } else {
        return filevineClient.getProjectDocuments(payload.projectId, payload);
      }
    
    case MESSAGE_TYPES.GET_FOLDER_TREE:
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      // Use web API client if using cookie-based auth
      if (authManager.getState().auth?.usingWebApi) {
        return webApiClient.getProjectFolderTree(payload.projectId, payload);
      } else {
        throw new Error('Folder tree only available with web API');
      }
    
    case MESSAGE_TYPES.DOWNLOAD_FOLDER:
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      // Queue all documents in a folder for download
      return downloadManager.queueFolderDownload(payload);
    
    case MESSAGE_TYPES.GET_CURRENT_PROJECT:
      // Forward request to content script on active tab
      try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        
        if (!tab) {
          console.log('[Filevine Plugin] No active tab found');
          return { projectId: null };
        }
        
        if (!tab.url?.includes('filevineapp.com')) {
          console.log('[Filevine Plugin] Active tab is not a Filevine page:', tab.url);
          return { projectId: null };
        }
        
        // Try to extract project ID directly from URL as fallback
        const urlMatch = tab.url.match(/\/projects?\/(\d+)/i);
        if (urlMatch) {
          const projectId = urlMatch[1];
          console.log('[Filevine Plugin] Found project ID from URL:', projectId);
          return { projectId, pageType: 'project', url: tab.url };
        }
        
        // Try to send message to content script (may fail if content script not loaded)
        try {
          const response = await chrome.tabs.sendMessage(tab.id, {
            type: MESSAGE_TYPES.GET_CURRENT_PROJECT
          });
          if (response?.projectId) {
            return response;
          }
        } catch (contentScriptError) {
          // Content script might not be loaded yet - that's okay, we already tried URL extraction
          console.log('[Filevine Plugin] Content script not ready, using URL extraction');
        }
        
        return { projectId: null };
      } catch (error) {
        console.error('[Filevine Plugin] Failed to get current project:', error);
        return { projectId: null };
      }
    
    // =====================================
    // Downloads
    // =====================================
    
    case MESSAGE_TYPES.DOWNLOAD_FILE:
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      return downloadManager.queueDownload(payload);
    
    case 'get_download_state':
      return downloadManager.getState();
    
    case 'cancel_download':
      return downloadManager.cancelDownload(payload.docId);
    
    case MESSAGE_TYPES.OPEN_VIEWER:
      return downloadManager.openFile(payload.docId);
    
    case MESSAGE_TYPES.VIEW_FILE_DIRECT:
      return downloadManager.viewFileDirect(payload);

    case MESSAGE_TYPES.OPEN_FOLDER_AS_DICOM:
      return downloadManager.openFolderAsDicom(payload);

    case 'GET_FILE':
    case 'get_file':
      // Try to get file from cache first
      let file = await downloadManager.getFile(payload.docId);

      // If not in cache and projectId is provided, download from Filevine
      if (!file && payload.projectId) {
        console.log('[Background] File not in cache, downloading from Filevine...', payload.docId);
        try {
          // Use downloadFileDirectly which handles auth state and API client selection
          await downloadManager.downloadFileDirectly({
            docId: payload.docId,
            projectId: payload.projectId,
            filename: payload.filename || 'download.dcm',
            folderPath: payload.folderPath || [],
            mimeType: payload.mimeType || 'application/dicom'
          });

          // Now retrieve it from cache
          file = await downloadManager.getFile(payload.docId);
          console.log('[Background] File downloaded and cached successfully');
        } catch (error) {
          console.error('[Background] Failed to download file from Filevine:', error);
          return { file: null, error: error.message };
        }
      }

      if (!file) {
        return { file: null };
      }

      // Convert blob to data URL since blobs can't be sent through message passing
      const reader = new FileReader();
      const dataUrl = await new Promise((resolve, reject) => {
        reader.onloadend = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsDataURL(file.blob);
      });

      return {
        file: {
          dataUrl,
          metadata: file.metadata
        }
      };

    case 'GET_SERIES':
      const series = await downloadManager.getSeries(payload.seriesId);
      return { series };

    case 'GET_PROJECT_DICOM_FILES':
      const dicomFiles = await downloadManager.getProjectDicomFiles(payload.projectId);
      return { files: dicomFiles };

    case 'OPEN_SERIES':
      return downloadManager.openSeries(payload.seriesId);

    case 'delete_file':
      return downloadManager.deleteFile(payload.docId);
    
    case 'clear_all_files':
      return downloadManager.clearAllFiles();

    // =====================================
    // Echomark Watermarking
    // =====================================

    case 'WATERMARK_DOCUMENT':
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      return echomarkHandler.watermarkDocument(payload);

    case 'GET_PROJECT_CONTACTS':
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      // Get project contacts/participants for recipient selection
      const authForContacts = authManager.getState();
      if (authForContacts.auth?.usingWebApi) {
        return webApiClient.getProjectContacts(payload.projectId);
      } else {
        return filevineClient.getProjectContacts(payload.projectId);
      }

    case 'GET_MARKING_SCHEMAS':
      // Get marking schemas for a document (for leak investigation)
      if (payload.docId) {
        return echomarkHandler.getMarkingSchemas(payload.docId);
      } else {
        return echomarkHandler.getAllMarkingSchemas();
      }

    // =====================================
    // Generic API passthrough
    // =====================================
    
    case MESSAGE_TYPES.API_REQUEST:
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }
      return filevineClient.request(
        payload.method || 'GET',
        payload.endpoint,
        { params: payload.params, data: payload.data }
      );

    // =====================================
    // Custom Fields
    // =====================================

    case 'create_custom_field':
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }

      // Make sure web API client is initialized
      const customFieldAuthState = authManager.getState();
      if (!webApiClient.isAuthenticated() && customFieldAuthState.auth?.cookie) {
        webApiClient.setCredentials({
          cookie: customFieldAuthState.auth.cookie,
          userId: customFieldAuthState.auth.userId,
          orgId: customFieldAuthState.auth.orgId
        });
      }

      return webApiClient.createCustomField(
        payload.orgId,
        payload.sectionId,
        payload.fieldData
      );

    case 'get_custom_project_type':
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }

      // Make sure web API client is initialized
      const projectTypeAuthState = authManager.getState();
      if (!webApiClient.isAuthenticated() && projectTypeAuthState.auth?.cookie) {
        webApiClient.setCredentials({
          cookie: projectTypeAuthState.auth.cookie,
          userId: projectTypeAuthState.auth.userId,
          orgId: projectTypeAuthState.auth.orgId
        });
      }

      return webApiClient.getCustomProjectType(
        payload.orgId,
        payload.projectTypeId
      );

    case 'ai_set_api_key':
      await aiService.saveApiKey(payload.apiKey);
      return { success: true, configured: true };

    case 'ai_check_config':
      return {
        success: true,
        configured: aiService.isConfigured()
      };

    case 'ai_generate_fields':
      if (!aiService.isConfigured()) {
        throw new Error('AI Service not configured. Please set your Anthropic API key.');
      }

      return {
        success: true,
        fields: await aiService.generateFields(
          payload.requirements,
          payload.context || {}
        )
      };

    case 'ai_create_fields_batch':
      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }

      // Make sure web API client is initialized
      const batchAuthState = authManager.getState();
      if (!webApiClient.isAuthenticated() && batchAuthState.auth?.cookie) {
        webApiClient.setCredentials({
          cookie: batchAuthState.auth.cookie,
          userId: batchAuthState.auth.userId,
          orgId: batchAuthState.auth.orgId
        });
      }

      // Create fields sequentially
      const results = [];
      for (const fieldData of payload.fields) {
        try {
          const result = await webApiClient.createCustomField(
            payload.orgId,
            payload.sectionId,
            fieldData
          );
          results.push({
            success: true,
            field: fieldData,
            result: result
          });
        } catch (error) {
          results.push({
            success: false,
            field: fieldData,
            error: error.message
          });
        }
      }

      return {
        success: true,
        results: results,
        successCount: results.filter(r => r.success).length,
        failureCount: results.filter(r => !r.success).length
      };

    case 'ANALYZE_RADIOLOGY':
      // Send DICOM radiology analysis request to Claude API
      if (!aiService.isConfigured()) {
        throw new Error('AI Service not configured. Please set your Anthropic API key.');
      }

      console.log('[Background] Sending radiology analysis request to Claude API');

      try {
        // Use the existing AI service to make the request
        const response = await aiService.makeAnthropicRequest(payload.request);

        console.log('[Background] Radiology analysis complete');

        return {
          success: true,
          data: response
        };
      } catch (error) {
        console.error('[Background] Radiology analysis failed:', error);
        throw error;
      }

    case 'PAGE_CONTEXT_UPDATE':
      // Forward page context updates from content script to sidebar
      console.log('[Filevine Plugin] Page context update from content script:', payload.context);

      // Forward to all extension views (sidebars)
      chrome.runtime.sendMessage({
        type: 'PAGE_CONTEXT_UPDATE',
        context: payload.context
      }).catch(err => {
        // It's OK if there's no receiver (sidebar might not be open)
        console.log('[Filevine Plugin] Could not forward page context (sidebar may be closed)');
      });

      return { success: true };

    // =====================================
    // Filevine Document Upload
    // =====================================

    case 'UPLOAD_DOCUMENT_TO_FILEVINE':
      console.log('[Background] Upload request received');
      console.log('[Background] Payload keys:', Object.keys(payload || {}));
      console.log('[Background] Payload.dataUrl type:', typeof payload?.dataUrl);
      console.log('[Background] Payload.dataUrl length:', payload?.dataUrl?.length || 0);

      if (!authManager.isAuthenticated()) {
        throw new Error('Not authenticated');
      }

      // Make sure web API client is initialized
      const uploadAuthState = authManager.getState();
      if (!webApiClient.isAuthenticated() && uploadAuthState.auth?.cookie) {
        webApiClient.setCredentials({
          cookie: uploadAuthState.auth.cookie,
          userId: uploadAuthState.auth.userId,
          orgId: uploadAuthState.auth.orgId
        });
      }

      // Get upload service
      const uploadService = getFilevineUploadService(webApiClient, authManager);

      // Convert base64 data URL to Blob
      const uploadDataUrl = payload.dataUrl;
      const { filename, projectId, folderId } = payload;

      if (!uploadDataUrl) {
        throw new Error('No dataUrl provided in payload');
      }

      // Extract base64 data and content type
      const uploadMatches = uploadDataUrl.match(/^data:(.+);base64,(.+)$/);
      if (!uploadMatches) {
        console.error('[Background] Invalid data URL format. Data URL prefix:', uploadDataUrl?.substring(0, 100));
        throw new Error('Invalid data URL format');
      }

      const uploadContentType = uploadMatches[1];
      const uploadBase64Data = uploadMatches[2];

      // Convert base64 to binary
      const uploadBinaryString = atob(uploadBase64Data);
      const uploadBytes = new Uint8Array(uploadBinaryString.length);
      for (let i = 0; i < uploadBinaryString.length; i++) {
        uploadBytes[i] = uploadBinaryString.charCodeAt(i);
      }

      // Create Blob
      const uploadBlob = new Blob([uploadBytes], { type: uploadContentType });

      console.log('[Background] Uploading document:', filename, 'size:', uploadBlob.size, 'bytes');

      // Upload document
      return uploadService.uploadDocument({
        file: uploadBlob,
        filename,
        projectId,
        folderId,
        onProgress: (progress) => {
          // Could forward progress updates to UI here if needed
          console.log('[Background] Upload progress:', progress.toFixed(1) + '%');
        }
      });

    default:
      console.warn('[Filevine Plugin] Unknown message type:', type);
      return { error: `Unknown message type: ${type}` };
  }
}

// Listen for tab updates to detect Filevine navigation
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete' && tab.url?.includes('filevineapp.com')) {
    // Could trigger content script injection here if needed
    console.log('[Filevine Plugin] Filevine tab detected:', tab.url);
  }
});

// Export for testing
export { handleMessage };
