import ScreenshotEditor from './screenshot-editor.js';

class FeedbackExtension {
  constructor() {
    this.screenshot = null;
    this.editorWindow = null;
    this.mediaRecorder = null;
    this.recordedChunks = [];
    this.recordingDialog = null;
    this.recordedVideo = null;
    
    // Initialize when DOM is loaded
    document.addEventListener('DOMContentLoaded', () => {
      this.initializeElements();
      this.attachEventListeners();
      this.loadSettings();
    });

    // Listen for messages from the editor window
    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      console.log('Popup received message:', message);
      try {
        if (message.type === 'screenshot-saved') {
          this.screenshot = message.screenshot;
          this.attachmentPreview.innerHTML = `
            <div class="screenshot-preview">
              <img src="${this.screenshot}" alt="Screenshot" style="max-width: 100%; height: auto;">
            </div>
          `;
          // Close the editor window if it exists
          if (this.editorWindow && !this.editorWindow.closed) {
            this.editorWindow.close();
          }
          sendResponse({ success: true });
        } else if (message.type === 'editor-ready') {
          console.log('Editor is ready, sending screenshot...');
          if (this.screenshot) {
            chrome.runtime.sendMessage({
              type: 'init-editor',
              screenshot: this.screenshot
            }, response => {
              console.log('Screenshot sent to editor, response:', response);
            });
          }
          sendResponse({ success: true });
        }
      } catch (error) {
        console.error('Error handling message:', error);
        sendResponse({ success: false, error: error.message });
      }
      return true; // Keep the message channel open for async response
    });
  }

  initializeElements() {
    // Form elements
    this.feedbackForm = document.getElementById('feedback-form');
    this.settingsPanel = document.getElementById('settings-panel');
    this.screenshotBtn = document.getElementById('screenshot-btn');
    this.recordBtn = document.getElementById('record-btn');
    this.submitFeedbackBtn = document.getElementById('submit-feedback');
    this.settingsBtn = document.getElementById('settings-btn');
    this.saveSettingsBtn = document.getElementById('save-settings');
    this.attachmentPreview = document.getElementById('attachment-preview');
    
    // Settings inputs
    this.jiraDomainInput = document.getElementById('jira-domain');
    this.jiraEmailInput = document.getElementById('jira-email');
    this.jiraTokenInput = document.getElementById('jira-token');
    this.jiraProjectInput = document.getElementById('jira-project');
    
    // Notification
    this.notification = document.getElementById('notification');

    // Create recording dialog
    this.recordingDialog = document.createElement('div');
    this.recordingDialog.className = 'recording-dialog hidden';
    this.recordingDialog.innerHTML = `
      <div class="recording-content">
        <div class="recording-status">Recording...</div>
        <button id="stop-recording" class="primary-button">Stop Recording</button>
      </div>
    `;
    document.body.appendChild(this.recordingDialog);
  }

  attachEventListeners() {
    if (this.screenshotBtn) {
      this.screenshotBtn.addEventListener('click', () => this.captureScreenshot());
    }
    if (this.recordBtn) {
      this.recordBtn.addEventListener('click', () => this.startScreenRecording());
    }
    if (this.submitFeedbackBtn) {
      this.submitFeedbackBtn.addEventListener('click', () => this.handleSubmit());
    }
    if (this.settingsBtn) {
      this.settingsBtn.addEventListener('click', () => this.showSettings());
    }
    if (this.saveSettingsBtn) {
      this.saveSettingsBtn.addEventListener('click', () => this.saveSettings());
    }
  }

  async loadSettings() {
    const settings = await chrome.storage.local.get(['jiraDomain', 'jiraEmail', 'jiraToken', 'jiraProject']);
    
    // Fill in settings if they exist
    if (settings.jiraDomain) this.jiraDomainInput.value = settings.jiraDomain;
    if (settings.jiraEmail) this.jiraEmailInput.value = settings.jiraEmail;
    if (settings.jiraToken) this.jiraTokenInput.value = settings.jiraToken;
    if (settings.jiraProject) this.jiraProjectInput.value = settings.jiraProject;

    // Show appropriate panel based on whether settings exist
    if (settings.jiraDomain && settings.jiraEmail && settings.jiraToken && settings.jiraProject) {
      this.showFeedbackForm();
    } else {
      this.showSettings();
    }
  }

  async saveSettings() {
    const domain = this.jiraDomainInput.value.trim();
    const email = this.jiraEmailInput.value.trim();
    const token = this.jiraTokenInput.value.trim();
    const project = this.jiraProjectInput.value.trim();

    if (!domain || !email || !token || !project) {
      this.showNotification('Please fill in all fields', 'error');
      return;
    }

    try {
      // Validate credentials by making a test API call
      const isValid = await this.validateJiraCredentials(domain, email, token);
      if (!isValid) {
        this.showNotification('Invalid Jira credentials', 'error');
        return;
      }

      // Save settings
      await chrome.storage.local.set({
        jiraDomain: domain,
        jiraEmail: email,
        jiraToken: token,
        jiraProject: project
      });

      this.showNotification('Settings saved successfully', 'success');
      this.showFeedbackForm();
    } catch (error) {
      console.error('Error saving settings:', error);
      this.showNotification('Error saving settings: ' + error.message, 'error');
    }
  }

  async validateJiraCredentials(domain, email, token) {
    try {
      const response = await fetch(`https://${domain}/rest/api/2/myself`, {
        method: 'GET',
        headers: {
          'Authorization': `Basic ${btoa(`${email}:${token}`)}`,
          'Accept': 'application/json'
        }
      });
      return response.ok;
    } catch (error) {
      console.error('Error validating Jira credentials:', error);
      return false;
    }
  }

  async handleSubmit() {
    try {
      const settings = await chrome.storage.local.get(['jiraDomain', 'jiraEmail', 'jiraToken', 'jiraProject']);
      if (!settings.jiraDomain || !settings.jiraEmail || !settings.jiraToken || !settings.jiraProject) {
        this.showNotification('Please configure Jira settings first', 'error');
        this.showSettings();
        return;
      }

      const type = document.getElementById('feedback-type').value;
      const title = document.getElementById('feedback-title').value;
      const description = document.getElementById('feedback-description').value;

      if (!title || !description) {
        this.showNotification('Please fill in all required fields', 'error');
        return;
      }

      // Map feedback type to standard Jira issue types
      let issueType;
      switch (type) {
        case 'Bug':
          issueType = 'Bug';
          break;
        case 'Review':
          issueType = 'Review';
          break;
        case 'Task':
          issueType = 'Task';
          break;
        default:
          issueType = 'Task';
      }

      // Get current tab URL for context
      const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
      const contextInfo = `
Reported from: ${tab.url}
Browser: ${navigator.userAgent}
Timestamp: ${new Date().toISOString()}

Description:
${description}
      `;

      const formData = {
        fields: {
          project: {
            key: settings.jiraProject
          },
          summary: title,
          description: contextInfo,
          issuetype: {
            name: issueType
          },
          labels: ["feedback-extension"]
        }
      };

      console.log('Submitting to Jira with data:', JSON.stringify(formData, null, 2));
      const response = await this.submitToJira(formData);
      
      // If we have a screenshot or video, attach it to the created issue
      if (response.key) {
        if (this.screenshot) {
          await this.attachScreenshotToIssue(response.key, this.screenshot);
        }
        if (this.recordedVideo) {
          await this.attachVideoToIssue(response.key, this.recordedVideo);
        }
      }

      if (response.key) {
        this.showNotification(`Issue ${response.key} created successfully!`, 'success');
        document.getElementById('feedback-title').value = '';
        document.getElementById('feedback-description').value = '';
        this.attachmentPreview.innerHTML = '';
        this.screenshot = null;
        this.recordedVideo = null;
      }
    } catch (error) {
      console.error('Full error details:', error);
      this.showNotification('Error submitting feedback: ' + error.message, 'error');
    }
  }

  async submitToJira(formData) {
    const settings = await chrome.storage.local.get(['jiraDomain', 'jiraEmail', 'jiraToken']);
    
    try {
      // First, get available issue types for the project
      const metaResponse = await fetch(`https://${settings.jiraDomain}/rest/api/2/issue/createmeta?projectKeys=${formData.fields.project.key}&expand=projects.issuetypes.fields`, {
        method: 'GET',
        headers: {
          'Authorization': `Basic ${btoa(`${settings.jiraEmail}:${settings.jiraToken}`)}`,
          'Accept': 'application/json'
        }
      });

      const metaData = await metaResponse.json();
      console.log('Project metadata:', metaData);

      if (!metaResponse.ok) {
        throw new Error('Failed to get project metadata');
      }

      // Get available issue types
      const project = metaData.projects[0];
      if (!project) {
        throw new Error('Project not found or no access');
      }

      const availableTypes = project.issuetypes.map(type => type.name);
      console.log('Available issue types:', availableTypes);

      // If the desired issue type isn't available, fall back to Task
      if (!availableTypes.includes(formData.fields.issuetype.name)) {
        console.log(`Issue type ${formData.fields.issuetype.name} not available, falling back to Task`);
        formData.fields.issuetype.name = 'Task';
      }

      // Create the issue
      const response = await fetch(`https://${settings.jiraDomain}/rest/api/2/issue`, {
        method: 'POST',
        headers: {
          'Authorization': `Basic ${btoa(`${settings.jiraEmail}:${settings.jiraToken}`)}`,
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(formData)
      });

      const responseData = await response.json();
      console.log('Jira API Response:', responseData);

      if (!response.ok) {
        if (responseData.errors) {
          const errorMessage = Object.entries(responseData.errors)
            .map(([field, error]) => `${field}: ${error}`)
            .join(', ');
          throw new Error(errorMessage);
        } else if (responseData.errorMessages) {
          throw new Error(responseData.errorMessages.join(', '));
        } else {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
      }

      return responseData;
    } catch (error) {
      console.error('Error submitting to Jira:', error);
      console.error('Request data:', JSON.stringify(formData, null, 2));
      throw error;
    }
  }

  async attachScreenshotToIssue(issueKey, screenshotDataUrl) {
    try {
      const settings = await chrome.storage.local.get(['jiraDomain', 'jiraEmail', 'jiraToken']);
      
      // Convert base64 data URL to blob
      const base64Data = screenshotDataUrl.replace(/^data:image\/png;base64,/, '');
      const byteCharacters = atob(base64Data);
      const byteArrays = [];
      
      for (let offset = 0; offset < byteCharacters.length; offset += 512) {
        const slice = byteCharacters.slice(offset, offset + 512);
        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
          byteNumbers[i] = slice.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
      }
      
      const blob = new Blob(byteArrays, { type: 'image/png' });
      
      // Create form data with the screenshot
      const formData = new FormData();
      formData.append('file', blob, 'screenshot.png');

      // Upload the attachment
      const response = await fetch(`https://${settings.jiraDomain}/rest/api/2/issue/${issueKey}/attachments`, {
        method: 'POST',
        headers: {
          'Authorization': `Basic ${btoa(`${settings.jiraEmail}:${settings.jiraToken}`)}`,
          'X-Atlassian-Token': 'no-check'  // Required for file uploads
        },
        body: formData
      });

      if (!response.ok) {
        const error = await response.text();
        throw new Error(`Failed to attach screenshot: ${error}`);
      }

      console.log('Screenshot attached successfully');
    } catch (error) {
      console.error('Error attaching screenshot:', error);
      throw new Error('Failed to attach screenshot: ' + error.message);
    }
  }

  async attachVideoToIssue(issueKey, videoBlob) {
    try {
      const settings = await chrome.storage.local.get(['jiraDomain', 'jiraEmail', 'jiraToken']);
      
      // Create form data with the video
      const formData = new FormData();
      formData.append('file', videoBlob, 'screen-recording.webm');

      // Upload the attachment
      const response = await fetch(`https://${settings.jiraDomain}/rest/api/2/issue/${issueKey}/attachments`, {
        method: 'POST',
        headers: {
          'Authorization': `Basic ${btoa(`${settings.jiraEmail}:${settings.jiraToken}`)}`,
          'X-Atlassian-Token': 'no-check'  // Required for file uploads
        },
        body: formData
      });

      if (!response.ok) {
        const error = await response.text();
        throw new Error(`Failed to attach video: ${error}`);
      }

      console.log('Video attached successfully');
    } catch (error) {
      console.error('Error attaching video:', error);
      throw new Error('Failed to attach video: ' + error.message);
    }
  }

  async captureScreenshot() {
    try {
      // Get current tab
      const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
      console.log('Current tab:', tab);
      
      // Capture the visible tab
      console.log('Capturing screenshot...');
      const screenshot = await chrome.tabs.captureVisibleTab(null, {
        format: 'png'
      });
      console.log('Screenshot captured:', screenshot?.substring(0, 100) + '...');

      // Verify screenshot data
      if (!screenshot || !screenshot.startsWith('data:image')) {
        throw new Error('Invalid screenshot data');
      }

      // Store the screenshot data
      this.screenshot = screenshot;

      // Calculate window dimensions
      const maxWidth = Math.min(1200, window.screen.availWidth * 0.8);
      const maxHeight = Math.min(800, window.screen.availHeight * 0.8);
      const left = (window.screen.availWidth - maxWidth) / 2;
      const top = (window.screen.availHeight - maxHeight) / 2;

      // Open editor window
      console.log('Opening editor window...');
      const editorUrl = chrome.runtime.getURL('editor.html');
      this.editorWindow = window.open(
        editorUrl,
        'screenshot-editor',
        `width=${maxWidth},height=${maxHeight},left=${left},top=${top},resizable=yes`
      );

      if (!this.editorWindow) {
        throw new Error('Could not open editor window. Please allow popups for this extension.');
      }

      // Send screenshot to background script
      chrome.runtime.sendMessage({
        type: 'init-editor',
        screenshot: this.screenshot
      }, response => {
        console.log('Screenshot sent to background, response:', response);
      });

    } catch (error) {
      console.error('Screenshot error:', error);
      this.showNotification('Error capturing screenshot: ' + error.message, 'error');
    }
  }

  async startScreenRecording() {
    try {
      // Request screen capture
      const stream = await navigator.mediaDevices.getDisplayMedia({ 
        video: { 
          cursor: "always",
          frameRate: { ideal: 30 }
        },
        audio: {
          echoCancellation: true,
          noiseSuppression: true,
          sampleRate: 44100
        }
      });

      // Create MediaRecorder
      this.mediaRecorder = new MediaRecorder(stream, {
        mimeType: 'video/webm;codecs=vp9',
        videoBitsPerSecond: 3000000 // 3 Mbps
      });

      // Set up recording handlers
      this.recordedChunks = [];
      this.mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
          this.recordedChunks.push(event.data);
        }
      };

      // Handle recording stop
      this.mediaRecorder.onstop = async () => {
        // Hide recording dialog
        this.recordingDialog.classList.add('hidden');

        // Stop all tracks
        stream.getTracks().forEach(track => track.stop());

        // Create blob from recorded chunks
        const blob = new Blob(this.recordedChunks, { type: 'video/webm' });
        
        // Convert to MP4 using FFmpeg.js (to be implemented)
        try {
          const mp4Blob = await this.convertToMP4(blob);
          
          // Create object URL for preview
          const videoURL = URL.createObjectURL(mp4Blob);
          
          // Add video preview to attachment preview
          this.attachmentPreview.innerHTML = `
            <div class="video-preview">
              <video src="${videoURL}" controls style="max-width: 100%; height: auto;"></video>
            </div>
          `;

          // Store the video blob for later submission
          this.recordedVideo = mp4Blob;

          // Show the main form again and restore window size
          document.body.classList.remove('recording');
          this.feedbackForm.classList.remove('hidden');
          window.resizeTo(400, 600); // Restore original size
          
          this.showNotification('Recording saved successfully!', 'success');
        } catch (error) {
          console.error('Error converting video:', error);
          this.showNotification('Error converting video: ' + error.message, 'error');
        }
      };

      // Start recording
      this.mediaRecorder.start(1000); // Collect data every second

      // Hide the main form and show recording dialog
      document.body.classList.add('recording');
      this.feedbackForm.classList.add('hidden');
      this.recordingDialog.classList.remove('hidden');

      // Set up stop recording button
      const stopButton = document.getElementById('stop-recording');
      stopButton.onclick = () => {
        if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
          this.mediaRecorder.stop();
        }
      };

      // Minimize window to only show recording controls
      window.resizeTo(300, 100);

    } catch (error) {
      console.error('Screen recording error:', error);
      this.showNotification('Error starting screen recording: ' + error.message, 'error');
      // Make sure main form is visible if there's an error
      document.body.classList.remove('recording');
      this.feedbackForm.classList.remove('hidden');
    }
  }

  async convertToMP4(webmBlob) {
    // For now, we'll just return the webm blob
    // In a future update, we can implement proper conversion to MP4
    return webmBlob;
  }

  showSettings() {
    this.settingsPanel.classList.remove('hidden');
    this.feedbackForm.classList.add('hidden');
  }

  showFeedbackForm() {
    this.settingsPanel.classList.add('hidden');
    this.feedbackForm.classList.remove('hidden');
  }

  showNotification(message, type = 'info') {
    this.notification.textContent = message;
    this.notification.className = `notification ${type}`;
    this.notification.classList.remove('hidden');
    
    setTimeout(() => {
      this.notification.classList.add('hidden');
    }, 5000);
  }
}

// Initialize the extension
new FeedbackExtension();