/**
 * Popup UI Controller
 * 
 * Manages the extension popup interface including project browsing,
 * file selection, and download management.
 */

import { MESSAGE_TYPES, CONNECTION_STATE } from '../lib/constants.js';

class PopupController {
  constructor() {
    this.state = {
      connectionState: CONNECTION_STATE.DISCONNECTED,
      auth: null,
      projects: [],
      selectedProject: null,
      currentFolder: null,
      folderPath: [], // Array of { id, name } for breadcrumb navigation
      documents: [],
      folders: [], // Array of folder objects
      downloads: { queue: [], active: [] },
      showDownloads: false
    };

    this.elements = {};
    this.debounceTimer = null;
  }

  /**
   * Initialize the popup
   */
  async init() {
    this.cacheElements();
    this.attachEventListeners();
    await this.checkAuthState();
    this.listenForMessages();
  }

  /**
   * Cache DOM element references
   */
  cacheElements() {
    this.elements = {
      connectionStatus: document.getElementById('connection-status'),
      statusText: document.querySelector('.status-text'),
      connectionPanel: document.getElementById('connection-panel'),
      mainPanel: document.getElementById('main-panel'),
      downloadPanel: document.getElementById('download-panel'),
      orgSelector: document.getElementById('org-selector'),
      orgSelect: document.getElementById('org-select'),
      projectSearch: document.getElementById('project-search'),
      refreshBtn: document.getElementById('refresh-btn'),
      projectList: document.getElementById('project-list'),
      fileBrowser: document.getElementById('file-browser'),
      backToProjects: document.getElementById('back-to-projects'),
      currentProjectName: document.getElementById('current-project-name'),
      fileList: document.getElementById('file-list'),
      downloadList: document.getElementById('download-list'),
      toggleDownloads: document.getElementById('toggle-downloads'),
      downloadCount: document.getElementById('download-count'),
      clearDownloads: document.getElementById('clear-downloads'),
      settingsBtn: document.getElementById('settings-btn')
    };
  }

  /**
   * Attach event listeners
   */
  attachEventListeners() {
    // Project search
    this.elements.projectSearch?.addEventListener('input', (e) => {
      this.debounce(() => this.searchProjects(e.target.value), 300);
    });

    // Refresh button
    this.elements.refreshBtn?.addEventListener('click', () => {
      this.loadProjects();
    });

    // Back to projects
    this.elements.backToProjects?.addEventListener('click', () => {
      this.showProjectList();
    });

    // Org selector
    this.elements.orgSelect?.addEventListener('change', (e) => {
      this.switchOrg(e.target.value);
    });

    // Toggle downloads panel
    this.elements.toggleDownloads?.addEventListener('click', () => {
      this.toggleDownloadsPanel();
    });

    // Clear downloads
    this.elements.clearDownloads?.addEventListener('click', () => {
      this.clearDownloads();
    });
  }

  /**
   * Check authentication state
   */
  async checkAuthState() {
    try {
      const response = await chrome.runtime.sendMessage({
        type: MESSAGE_TYPES.GET_AUTH_STATE
      });

      if (response?.authenticated) {
        this.state.connectionState = CONNECTION_STATE.CONNECTED;
        this.state.auth = response.auth;
        this.updateConnectionUI();
        this.setupOrgSelector();
        await this.loadProjects();
      } else {
        this.state.connectionState = response?.state || CONNECTION_STATE.DISCONNECTED;
        this.updateConnectionUI();
      }
    } catch (error) {
      console.error('Failed to check auth state:', error);
      this.state.connectionState = CONNECTION_STATE.ERROR;
      this.updateConnectionUI();
    }
  }

  /**
   * Update connection status UI
   */
  updateConnectionUI() {
    const { connectionStatus, statusText, connectionPanel, mainPanel } = this.elements;
    
    // Update status indicator
    connectionStatus.className = `status ${this.state.connectionState}`;
    
    const statusMessages = {
      [CONNECTION_STATE.DISCONNECTED]: 'Disconnected',
      [CONNECTION_STATE.DETECTING]: 'Detecting...',
      [CONNECTION_STATE.CONNECTED]: 'Connected',
      [CONNECTION_STATE.ERROR]: 'Error'
    };
    statusText.textContent = statusMessages[this.state.connectionState] || 'Unknown';

    // Show appropriate panel
    if (this.state.connectionState === CONNECTION_STATE.CONNECTED) {
      connectionPanel.classList.add('hidden');
      mainPanel.classList.remove('hidden');
    } else {
      connectionPanel.classList.remove('hidden');
      mainPanel.classList.add('hidden');
    }
  }

  /**
   * Setup org selector for multi-org users
   */
  setupOrgSelector() {
    const { orgSelector, orgSelect } = this.elements;
    const orgs = this.state.auth?.orgs || [];

    if (orgs.length > 1) {
      orgSelect.innerHTML = orgs.map(org => 
        `<option value="${org.orgId}" ${org.orgId === this.state.auth.orgId ? 'selected' : ''}>
          ${org.name || org.orgId}
        </option>`
      ).join('');
      orgSelector.classList.remove('hidden');
    } else {
      orgSelector.classList.add('hidden');
    }
  }

  /**
   * Load projects from API
   */
  async loadProjects(search = '') {
    const { projectList } = this.elements;
    projectList.innerHTML = '<div class="loading">Loading projects...</div>';

    try {
      console.log('[Popup] Requesting projects, search:', search);
      const response = await chrome.runtime.sendMessage({
        type: MESSAGE_TYPES.GET_PROJECTS,
        search,
        limit: 100  // Request more projects
      });

      console.log('[Popup] Projects response:', response);
      console.log('[Popup] Response type:', typeof response);
      console.log('[Popup] Response keys:', response ? Object.keys(response) : 'null');
      
      // Handle different response formats
      let projects = [];
      if (response) {
        if (response.items && Array.isArray(response.items)) {
          projects = response.items;
        } else if (Array.isArray(response)) {
          projects = response;
        } else if (response.data && Array.isArray(response.data)) {
          projects = response.data;
        }
      }
      
      console.log('[Popup] Extracted projects:', projects.length);
      this.state.projects = projects;
      this.renderProjectList();
    } catch (error) {
      console.error('[Popup] Failed to load projects:', error);
      projectList.innerHTML = `<div class="empty">Failed to load projects: ${error.message}</div>`;
    }
  }

  /**
   * Search projects
   */
  searchProjects(query) {
    this.loadProjects(query);
  }

  /**
   * Render project list
   */
  renderProjectList() {
    const { projectList } = this.elements;
    
    if (!this.state.projects.length) {
      projectList.innerHTML = '<div class="empty">No projects found</div>';
      return;
    }

    projectList.innerHTML = this.state.projects.map(project => {
      // Handle different field names from Filevine API
      const projectId = project.projectID || project.projectId || project.id;
      const projectName = project.projectName || project.name || 'Unnamed';
      const projectType = project.projectTypeName || project.projectType || project.type || '';
      
      return `
        <div class="list-item" data-project-id="${projectId}">
          <span class="icon">📁</span>
          <div class="info">
            <div class="name">${this.escapeHtml(projectName)}</div>
            <div class="meta">${this.escapeHtml(projectType)}</div>
          </div>
        </div>
      `;
    }).join('');

    // Attach click handlers
    projectList.querySelectorAll('.list-item').forEach(item => {
      item.addEventListener('click', () => {
        const projectId = item.dataset.projectId;
        this.selectProject(projectId);
      });
    });
  }

  /**
   * Select a project and show its documents
   */
  async selectProject(projectId) {
    const project = this.state.projects.find(
      p => String(p.projectID || p.projectId || p.id) === String(projectId)
    );
    
    if (!project) {
      console.error('[Popup] Project not found:', projectId);
      return;
    }

    console.log('[Popup] Selecting project:', project);
    this.state.selectedProject = project;
    this.elements.currentProjectName.textContent = project.projectName || project.name || 'Unnamed';
    
    // Show file browser
    this.elements.fileBrowser.classList.remove('hidden');
    document.querySelector('.browser:not(#file-browser)').classList.add('hidden');
    
    // Use projectID from the project object
    const actualProjectId = project.projectID || project.projectId || project.id;
    await this.loadDocuments(actualProjectId);
  }

  /**
   * Show project list
   */
  showProjectList() {
    this.state.selectedProject = null;
    this.state.currentFolder = null;
    this.state.folderPath = [];
    this.elements.fileBrowser.classList.add('hidden');
    document.querySelector('.browser:not(#file-browser)').classList.remove('hidden');
  }

  /**
   * Load documents and folders for a project
   */
  async loadDocuments(projectId, folderID = null) {
    const { fileList } = this.elements;
    fileList.innerHTML = '<div class="loading">Loading...</div>';

    try {
      console.log('[Popup] Loading documents for project:', projectId, 'folderID:', folderID);
      
      // Load documents
      const docsResponse = await chrome.runtime.sendMessage({
        type: MESSAGE_TYPES.GET_PROJECT_DOCS,
        projectId: String(projectId),
        folderID: folderID,
        limit: 100,
        offset: 0
      });

      console.log('[Popup] Documents response:', docsResponse);
      
      // Handle different response formats
      let documents = [];
      if (docsResponse) {
        if (docsResponse.items && Array.isArray(docsResponse.items)) {
          documents = docsResponse.items;
        } else if (Array.isArray(docsResponse)) {
          documents = docsResponse;
        } else if (docsResponse.data && Array.isArray(docsResponse.data)) {
          documents = docsResponse.data;
        }
      }
      
      // Load folder tree to get subfolders
      let folders = [];
      try {
        const folderTreeResponse = await chrome.runtime.sendMessage({
          type: MESSAGE_TYPES.GET_FOLDER_TREE,
          projectId: String(projectId)
        });
        
        console.log('[Popup] Folder tree response:', folderTreeResponse);
        
        if (folderTreeResponse && folderTreeResponse.childrenLookup) {
          // Get folders for current folder (or root)
          // childrenLookup uses string keys, so convert to string
          const currentFolderID = folderID || folderTreeResponse.rootFolderID;
          const currentFolderIDStr = String(currentFolderID);
          
          // Try both string and number keys
          const childFolderIDs = folderTreeResponse.childrenLookup[currentFolderIDStr] || 
                                 folderTreeResponse.childrenLookup[currentFolderID] || 
                                 [];
          
          console.log('[Popup] Current folder ID:', currentFolderID, '(string:', currentFolderIDStr + ')');
          console.log('[Popup] Child folder IDs:', childFolderIDs);
          console.log('[Popup] Children lookup keys:', Object.keys(folderTreeResponse.childrenLookup));
          console.log('[Popup] Folder lookup available:', !!folderTreeResponse.folderLookup);
          
          // Extract folder names from documents as fallback
          const folderNamesFromDocs = {};
          documents.forEach(doc => {
            if (doc.folderID && doc.folderName) {
              folderNamesFromDocs[doc.folderID] = doc.folderName;
            }
          });
          console.log('[Popup] Folder names from documents:', folderNamesFromDocs);
          
          // Look up folder details from folderLookup
          folders = childFolderIDs
            .map(folderId => {
              const folderIdStr = String(folderId);
              let folderName = null;
              
              // Try folderLookup first
              if (folderTreeResponse.folderLookup) {
                const folderDetails = folderTreeResponse.folderLookup[folderIdStr] || 
                                      folderTreeResponse.folderLookup[folderId];
                if (folderDetails) {
                  folderName = folderDetails.folderName || folderDetails.name;
                }
              }
              
              // Fallback to folder names from documents
              if (!folderName) {
                folderName = folderNamesFromDocs[folderId] || folderNamesFromDocs[folderIdStr];
              }
              
              // Final fallback
              if (!folderName) {
                folderName = `Folder ${folderId}`;
              }
              
              return {
                id: folderId,
                name: folderName,
                parentID: currentFolderID
              };
            })
            .filter(f => f); // Remove any null/undefined entries
          
          console.log('[Popup] Parsed folders:', folders.length, folders);
        } else {
          console.warn('[Popup] No childrenLookup in folder tree response');
          console.warn('[Popup] Folder tree response structure:', Object.keys(folderTreeResponse || {}));
        }
      } catch (error) {
        console.warn('[Popup] Could not load folder tree:', error);
        console.error('[Popup] Folder tree error details:', error);
      }
      
      console.log('[Popup] Extracted documents:', documents.length, 'folders:', folders.length);
      this.state.documents = documents;
      this.state.folders = folders;
      this.state.currentFolder = folderID;
      this.renderDocumentList();
    } catch (error) {
      console.error('[Popup] Failed to load documents:', error);
      fileList.innerHTML = `<div class="empty">Failed to load documents: ${error.message}</div>`;
    }
  }

  /**
   * Render document and folder list
   */
  renderDocumentList() {
    const { fileList } = this.elements;
    
    const folders = this.state.folders || [];
    const documents = this.state.documents || [];
    
    if (!folders.length && !documents.length) {
      fileList.innerHTML = '<div class="empty">No folders or documents found</div>';
      return;
    }

    let html = '';
    
    // Render folders first
    folders.forEach(folder => {
      html += `
        <div class="list-item folder-item" data-folder-id="${folder.id}">
          <span class="icon">📁</span>
          <div class="info">
            <div class="name">${this.escapeHtml(folder.name)}</div>
            <div class="meta">Folder</div>
          </div>
          <div class="actions">
            <button class="action-btn secondary download-folder-btn" data-folder-id="${folder.id}" title="Download all documents in folder">
              Download All
            </button>
          </div>
        </div>
      `;
    });
    
    // Render documents
    html += documents.map(doc => {
      // Handle different field names from Filevine API
      const docId = doc.id || doc.docId || doc.documentId;
      const filename = doc.filename || doc.name || doc.title || 'Unknown';
      const size = doc.size || 0;
      const icon = this.getFileIcon(filename);
      
      return `
        <div class="list-item" data-doc-id="${docId}">
          <span class="icon">${icon}</span>
          <div class="info">
            <div class="name">${this.escapeHtml(filename)}</div>
            <div class="meta">${this.formatFileSize(size)}</div>
          </div>
          <div class="actions">
            <button class="action-btn primary download-btn" data-doc-id="${docId}">
              Download
            </button>
          </div>
        </div>
      `;
    }).join('');
    
    fileList.innerHTML = html;

    // Attach folder click handlers
    fileList.querySelectorAll('.folder-item').forEach(item => {
      item.addEventListener('click', (e) => {
        if (!e.target.closest('.actions')) {
          const folderId = item.dataset.folderId;
          this.openFolder(folderId);
        }
      });
    });

    // Attach folder download handlers
    fileList.querySelectorAll('.download-folder-btn').forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.stopPropagation();
        const folderId = btn.dataset.folderId;
        this.downloadFolder(folderId);
      });
    });

    // Attach document download handlers
    fileList.querySelectorAll('.download-btn').forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.stopPropagation();
        const docId = btn.dataset.docId;
        this.downloadDocument(docId);
      });
    });
    
    // Update breadcrumb
    this.updateBreadcrumb();
  }
  
  /**
   * Open a folder
   */
  async openFolder(folderId) {
    const folder = this.state.folders.find(f => String(f.id) === String(folderId));
    if (!folder) {
      console.error('[Popup] Folder not found:', folderId);
      return;
    }
    
    // Add to folder path
    this.state.folderPath.push({
      id: folderId,
      name: folder.name
    });
    
    // Load documents in this folder
    const projectId = this.state.selectedProject?.projectID || this.state.selectedProject?.projectId || this.state.selectedProject?.id;
    await this.loadDocuments(projectId, folderId);
  }
  
  /**
   * Update breadcrumb navigation
   */
  updateBreadcrumb() {
    const breadcrumb = document.querySelector('#file-browser .breadcrumb');
    if (!breadcrumb) return;
    
    let html = '<button id="back-to-projects" class="text-btn">← Projects</button>';
    
    if (this.state.selectedProject) {
      html += `<span class="project-name">${this.escapeHtml(this.state.selectedProject.projectName || this.state.selectedProject.name)}</span>`;
    }
    
    // Add folder path
    this.state.folderPath.forEach((folder, index) => {
      html += ` <span class="separator">/</span> `;
      html += `<button class="text-btn folder-breadcrumb" data-folder-id="${folder.id}" data-path-index="${index}">${this.escapeHtml(folder.name)}</button>`;
    });
    
    breadcrumb.innerHTML = html;
    
    // Attach breadcrumb click handlers
    breadcrumb.querySelectorAll('.folder-breadcrumb').forEach(btn => {
      btn.addEventListener('click', () => {
        const pathIndex = parseInt(btn.dataset.pathIndex);
        // Navigate back to this folder
        this.state.folderPath = this.state.folderPath.slice(0, pathIndex + 1);
        const folderId = btn.dataset.folderId;
        const projectId = this.state.selectedProject?.projectID || this.state.selectedProject?.projectId || this.state.selectedProject?.id;
        this.loadDocuments(projectId, folderId);
      });
    });
  }
  
  /**
   * Download all documents in a folder
   */
  async downloadFolder(folderId) {
    const folder = this.state.folders.find(f => String(f.id) === String(folderId));
    if (!folder) {
      console.error('[Popup] Folder not found:', folderId);
      return;
    }
    
    const projectId = this.state.selectedProject?.projectID || this.state.selectedProject?.projectId || this.state.selectedProject?.id;
    
    try {
      console.log('[Popup] Downloading folder:', folder.name, 'folderId:', folderId);
      
      await chrome.runtime.sendMessage({
        type: MESSAGE_TYPES.DOWNLOAD_FOLDER,
        projectId: projectId,
        folderId: folderId,
        folderName: folder.name
      });
      
      // Update download count
      this.updateDownloadCount();
    } catch (error) {
      console.error('[Popup] Failed to download folder:', error);
      alert(`Failed to download folder: ${error.message}`);
    }
  }

  /**
   * Download a document
   */
  async downloadDocument(docId) {
    const doc = this.state.documents.find(d => String(d.id || d.docId || d.documentId) === String(docId));
    if (!doc) {
      console.error('[Popup] Document not found:', docId);
      return;
    }

    try {
      const actualDocId = doc.id || doc.docId || doc.documentId;
      const projectId = this.state.selectedProject?.projectID || this.state.selectedProject?.projectId || this.state.selectedProject?.id;
      
      const filename = doc.filename || doc.name || doc.title;
      
      console.log('[Popup] Downloading document:', {
        docId: actualDocId,
        projectId: projectId,
        filename: filename,
        docObject: doc // Log full doc object to see what fields are available
      });
      
      await chrome.runtime.sendMessage({
        type: MESSAGE_TYPES.DOWNLOAD_FILE,
        docId: actualDocId,
        projectId: projectId,
        filename: filename,
        mimeType: doc.mimeType || doc.contentType,
        autoOpen: true
      });

      // Update UI to show download started
      this.updateDownloadCount();
    } catch (error) {
      console.error('[Popup] Failed to start download:', error);
      alert(`Download failed: ${error.message}`);
    }
  }

  /**
   * Toggle downloads panel
   */
  toggleDownloadsPanel() {
    this.state.showDownloads = !this.state.showDownloads;
    
    if (this.state.showDownloads) {
      this.elements.downloadPanel.classList.remove('hidden');
      this.elements.mainPanel.classList.add('hidden');
      this.loadDownloadState();
    } else {
      this.elements.downloadPanel.classList.add('hidden');
      this.elements.mainPanel.classList.remove('hidden');
    }
  }

  /**
   * Load current download state
   */
  async loadDownloadState() {
    try {
      const state = await chrome.runtime.sendMessage({ type: 'get_download_state' });
      this.state.downloads = state;
      this.renderDownloadList();
    } catch (error) {
      console.error('Failed to load download state:', error);
    }
  }

  /**
   * Render download list
   */
  renderDownloadList() {
    const { downloadList } = this.elements;
    const allDownloads = [
      ...this.state.downloads.active,
      ...this.state.downloads.queue
    ];

    if (!allDownloads.length) {
      downloadList.innerHTML = '<div class="empty">No downloads</div>';
      return;
    }

    downloadList.innerHTML = allDownloads.map(dl => `
      <div class="download-item" data-doc-id="${dl.docId}">
        <div class="header">
          <span class="name">${this.escapeHtml(dl.filename)}</span>
          <span class="status ${dl.status}">${dl.status}</span>
        </div>
        ${dl.status === 'downloading' ? `
          <div class="progress-bar">
            <div class="fill" style="width: ${dl.progress}%"></div>
          </div>
        ` : ''}
        ${dl.error ? `<div class="error">${dl.error}</div>` : ''}
      </div>
    `).join('');
  }

  /**
   * Update download count badge
   */
  updateDownloadCount() {
    const count = this.state.downloads.queue.length + this.state.downloads.active.length;
    this.elements.downloadCount.textContent = count;
    this.elements.downloadCount.classList.toggle('hidden', count === 0);
  }

  /**
   * Clear all downloads
   */
  async clearDownloads() {
    try {
      await chrome.runtime.sendMessage({ type: 'clear_all_files' });
      this.state.downloads = { queue: [], active: [] };
      this.renderDownloadList();
      this.updateDownloadCount();
    } catch (error) {
      console.error('Failed to clear downloads:', error);
    }
  }

  /**
   * Switch organization
   */
  async switchOrg(orgId) {
    try {
      await chrome.runtime.sendMessage({ type: 'switch_org', orgId });
      this.state.auth.orgId = orgId;
      await this.loadProjects();
    } catch (error) {
      console.error('Failed to switch org:', error);
      alert(`Failed to switch organization: ${error.message}`);
    }
  }

  /**
   * Listen for messages from background
   */
  listenForMessages() {
    chrome.runtime.onMessage.addListener((message) => {
      switch (message.type) {
        case MESSAGE_TYPES.AUTH_STATE_CHANGED:
          this.state.connectionState = message.state?.authenticated 
            ? CONNECTION_STATE.CONNECTED 
            : CONNECTION_STATE.DISCONNECTED;
          this.state.auth = message.state?.auth;
          this.updateConnectionUI();
          if (message.state?.authenticated) {
            this.loadProjects();
          }
          break;

        case MESSAGE_TYPES.DOWNLOAD_PROGRESS:
          this.state.downloads = message.state;
          if (this.state.showDownloads) {
            this.renderDownloadList();
          }
          this.updateDownloadCount();
          break;

        case MESSAGE_TYPES.DOWNLOAD_COMPLETE:
          // Could show notification
          break;
      }
    });
  }

  /**
   * Utility: Debounce function calls
   */
  debounce(fn, delay) {
    clearTimeout(this.debounceTimer);
    this.debounceTimer = setTimeout(fn, delay);
  }

  /**
   * Utility: Escape HTML
   */
  escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  /**
   * Utility: Get file icon
   */
  getFileIcon(filename) {
    const ext = filename?.split('.').pop()?.toLowerCase();
    const icons = {
      pdf: '📄',
      doc: '📝',
      docx: '📝',
      xls: '📊',
      xlsx: '📊',
      ppt: '📽️',
      pptx: '📽️',
      jpg: '🖼️',
      jpeg: '🖼️',
      png: '🖼️',
      gif: '🖼️',
      dcm: '🏥',
      dicom: '🏥',
      zip: '📦',
      txt: '📃'
    };
    return icons[ext] || '📄';
  }

  /**
   * Utility: Format file size
   */
  formatFileSize(bytes) {
    if (!bytes) return '';
    const units = ['B', 'KB', 'MB', 'GB'];
    let size = bytes;
    let unitIndex = 0;
    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }
    return `${size.toFixed(1)} ${units[unitIndex]}`;
  }
}

// Initialize when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
  const popup = new PopupController();
  popup.init();
});
