import { autoUpdater } from 'electron-updater';
import { dialog, app } from 'electron';
import log from 'electron-log';
import { settingsStore } from './store';

// Track if update check was triggered manually by user
let isManualCheck = false;

// Function to update the GitHub token in autoUpdater
function updateGitHubToken(): void {
  const githubToken = settingsStore.get('githubToken');
  if (githubToken) {
    // Set via environment variable (preferred method for electron-updater)
    process.env.GH_TOKEN = githubToken;
    // Also set via requestHeaders as backup
    autoUpdater.requestHeaders = {
      'Authorization': `token ${githubToken}`
    };
    log.info('[UPDATE] GitHub token configured in autoUpdater');
    log.info(`[UPDATE] Token length: ${githubToken.length} characters`);
    log.info(`[UPDATE] Token starts with: ${githubToken.substring(0, 7)}...`);
    log.info(`[UPDATE] GH_TOKEN environment variable set: ${!!process.env.GH_TOKEN}`);
  } else {
    // Clear the authorization header if no token
    delete process.env.GH_TOKEN;
    autoUpdater.requestHeaders = {};
    log.warn('[UPDATE] No GitHub token configured - private repo access will fail');
  }
}

export function initializeUpdater(): void {
  // Configure logger
  autoUpdater.logger = log;

  // Allow updates in development for testing
  if (!app.isPackaged) {
    log.info('[UPDATE] Running in development mode');
    // Force dev updates for testing
    Object.defineProperty(app, 'isPackaged', {
      get() {
        return true;
      }
    });
  }

  // Check if auto-update is enabled
  if (!settingsStore.get('autoUpdate')) {
    log.info('Auto-update is disabled');
    return;
  }

  // Configure auto-updater
  autoUpdater.autoDownload = false;
  autoUpdater.autoInstallOnAppQuit = true;

  // Set initial GitHub token
  updateGitHubToken();

  // Listen for settings changes to update token dynamically
  settingsStore.settingsChanged$.subscribe(({ key, value }) => {
    if (key === 'githubToken') {
      log.info('GitHub token changed in settings, updating autoUpdater');
      updateGitHubToken();
    }
  });

  // Set up event handlers
  autoUpdater.on('checking-for-update', async () => {
    log.info('=====================================');
    log.info('[UPDATE] Checking for updates...');
    log.info(`[UPDATE] Current version: ${app.getVersion()}`);
    log.info(`[UPDATE] Feed URL: ${autoUpdater.getFeedURL()}`);
    log.info(`[UPDATE] Auto-download: ${autoUpdater.autoDownload}`);
    log.info(`[UPDATE] Has auth token: ${!!settingsStore.get('githubToken')}`);
    log.info('=====================================');

    // Debug: Try to fetch what electron-updater is fetching
    try {
      const githubToken = settingsStore.get('githubToken');
      const urls = [
        'https://api.github.com/repos/instructure/inst-agent/releases/latest',
        'https://github.com/instructure/inst-agent/releases.atom',
        'https://github.com/instructure/inst-agent/releases/download/latest/latest-mac.yml'
      ];

      for (const url of urls) {
        try {
          const headers: any = { 'User-Agent': 'Instructure-Agent' };
          if (githubToken) {
            headers['Authorization'] = `token ${githubToken}`;
          }

          log.info(`[UPDATE DEBUG] Fetching: ${url}`);
          const response = await fetch(url, { headers });
          const text = await response.text();

          log.info(`[UPDATE DEBUG] Response status: ${response.status}`);
          log.info(`[UPDATE DEBUG] Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`);

          // For API endpoint, try to parse and log the JSON
          if (url.includes('api.github.com') && response.status === 200) {
            try {
              const json = JSON.parse(text);
              log.info(`[UPDATE DEBUG] API Response - Version: ${json.tag_name}`);
              log.info(`[UPDATE DEBUG] API Response - Published at: ${json.published_at}`);
              log.info(`[UPDATE DEBUG] API Response - Assets count: ${json.assets?.length || 0}`);
              if (json.assets) {
                json.assets.forEach((asset: any) => {
                  log.info(`[UPDATE DEBUG]   - ${asset.name} (${asset.size} bytes)`);
                });
              }
              log.info(`[UPDATE DEBUG] Full API Response:\n${JSON.stringify(json, null, 2)}`);
            } catch (parseErr) {
              log.error(`[UPDATE DEBUG] Failed to parse API response as JSON`);
            }
          }

          log.info(`[UPDATE DEBUG] Response body (first 500 chars):\n${text.substring(0, 500)}`);
          log.info('---');
        } catch (err: any) {
          log.error(`[UPDATE DEBUG] Failed to fetch ${url}: ${err.message}`);
        }
      }
    } catch (err: any) {
      log.error('[UPDATE DEBUG] Debug fetch failed:', err);
    }
  });

  autoUpdater.on('update-available', (info) => {
    log.info('=====================================');
    log.info('[UPDATE] ✅ Update available!');
    log.info(`[UPDATE] New version: ${info.version}`);
    log.info(`[UPDATE] Release date: ${info.releaseDate}`);
    log.info(`[UPDATE] Release notes: ${info.releaseNotes}`);
    log.info('[UPDATE] Files:', info.files);
    log.info('=====================================');

    dialog.showMessageBox({
      type: 'info',
      title: 'Update Available',
      message: `A new version (${info.version}) is available. Would you like to download it now?`,
      buttons: ['Download', 'Later']
    }).then(result => {
      if (result.response === 0) {
        autoUpdater.downloadUpdate();
      }
    });
  });

  autoUpdater.on('update-not-available', (info) => {
    log.info('=====================================');
    log.info('[UPDATE] No updates available');
    log.info(`[UPDATE] Current version ${app.getVersion()} is the latest`);
    log.info('[UPDATE] Info:', info);
    log.info('=====================================');

    // Only show dialog if user manually checked for updates
    if (isManualCheck) {
      const currentVersion = app.getVersion();
      dialog.showMessageBox({
        type: 'info',
        title: 'No Updates Available',
        message: 'You\'re up to date!',
        detail: `Instructure Agent ${currentVersion} is the latest version.`,
        buttons: ['OK']
      });
    }

    // Reset manual check flag
    isManualCheck = false;
  });

  autoUpdater.on('error', (err) => {
    log.error('=====================================');
    log.error('[UPDATE] ❌ Error occurred');
    log.error(`[UPDATE] Error message: ${err.message}`);
    log.error(`[UPDATE] Error stack: ${err.stack}`);
    log.error('[UPDATE] Full error:', err);
    log.error('=====================================');

    // Show error dialog if user manually checked for updates
    if (isManualCheck) {
      let errorDetail = 'Please check your internet connection and try again later.';
      let errorMessage = 'Could not check for updates.';

      // Provide more specific error messages
      const errorStr = err.toString().toLowerCase();
      if (errorStr.includes('404') || errorStr.includes('not found')) {
        errorMessage = 'No releases found';
        errorDetail = 'No releases have been published yet for this repository. Please create a release first by pushing a version tag (e.g., git tag 1.0.0 && git push origin 1.0.0).';
      } else if (errorStr.includes('401') || errorStr.includes('unauthorized') || errorStr.includes('403') || errorStr.includes('forbidden')) {
        errorMessage = 'GitHub token issue';
        errorDetail = 'The GitHub token may be invalid or missing required permissions. Please check:\n\n1. Token has "repo" scope\n2. Token is not expired\n3. Repository is accessible with this token';
      } else if (errorStr.includes('network') || errorStr.includes('enotfound') || errorStr.includes('etimedout')) {
        errorMessage = 'Network error';
        errorDetail = 'Could not connect to GitHub. Please check your internet connection.';
      }

      dialog.showMessageBox({
        type: 'error',
        title: 'Update Check Failed',
        message: errorMessage,
        detail: errorDetail,
        buttons: ['OK']
      });
    }

    // Reset manual check flag
    isManualCheck = false;
  });

  autoUpdater.on('download-progress', (progressObj) => {
    log.info(`[UPDATE] Download progress: ${progressObj.percent.toFixed(2)}% (${progressObj.bytesPerSecond} bytes/sec)`);
  });

  autoUpdater.on('update-downloaded', (info) => {
    log.info('=====================================');
    log.info('[UPDATE] ✅ Update downloaded successfully!');
    log.info(`[UPDATE] Version: ${info.version}`);
    log.info('[UPDATE] Ready to install');
    log.info('=====================================');

    dialog.showMessageBox({
      type: 'info',
      title: 'Update Ready',
      message: 'Update downloaded. The application will restart to install the update.',
      buttons: ['Restart Now', 'Later']
    }).then(result => {
      if (result.response === 0) {
        autoUpdater.quitAndInstall();
      }
    });
  });

  // Check for updates on startup (silently)
  checkForUpdates();

  // Check for updates periodically (every 6 hours, silently)
  setInterval(() => {
    if (settingsStore.get('autoUpdate')) {
      checkForUpdates();
    }
  }, 6 * 60 * 60 * 1000);
}

/**
 * Check for updates
 * @param manual - true if triggered by user action (shows dialogs for no updates/errors)
 */
export function checkForUpdates(manual: boolean = false): void {
  log.info('=====================================');
  log.info(`[UPDATE] checkForUpdates called (manual: ${manual})`);
  log.info(`[UPDATE] Auto-update enabled: ${settingsStore.get('autoUpdate')}`);
  log.info(`[UPDATE] GitHub token configured: ${!!settingsStore.get('githubToken')}`);

  if (settingsStore.get('autoUpdate')) {
    isManualCheck = manual;
    log.info('[UPDATE] Initiating update check...');
    autoUpdater.checkForUpdates().catch(err => {
      log.error('[UPDATE] Failed to initiate check:', err);
    });
  } else if (manual) {
    // If auto-update is disabled but user manually checked, show message
    dialog.showMessageBox({
      type: 'info',
      title: 'Auto-Update Disabled',
      message: 'Automatic updates are currently disabled.',
      detail: 'Enable auto-updates in Settings to check for new versions.',
      buttons: ['OK']
    });
  }
}
