#!/usr/bin/env node

/**
 * MAILER npm postinstall script
 * Downloads the appropriate binary for the current platform from GitHub releases
 */

import { platform, arch } from 'os';
import { existsSync, mkdirSync, writeFileSync, chmodSync, unlinkSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import https from 'https';
import { pipeline } from 'stream';
import { promisify } from 'util';
import { createWriteStream } from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const streamPipeline = promisify(pipeline);

// Configuration
const REPO_BASE = 'https://code.foss.global/serve.zone/mailer';
const VERSION = process.env.npm_package_version || '1.0.0';

function getBinaryInfo() {
  const plat = platform();
  const architecture = arch();

  const platformMap = {
    'darwin': 'macos',
    'linux': 'linux',
    'win32': 'windows'
  };

  const archMap = {
    'x64': 'x64',
    'arm64': 'arm64'
  };

  const mappedPlatform = platformMap[plat];
  const mappedArch = archMap[architecture];

  if (!mappedPlatform || !mappedArch) {
    return { supported: false, platform: plat, arch: architecture };
  }

  let binaryName = `mailer-${mappedPlatform}-${mappedArch}`;
  if (plat === 'win32') {
    binaryName += '.exe';
  }

  return {
    supported: true,
    platform: mappedPlatform,
    arch: mappedArch,
    binaryName,
    originalPlatform: plat
  };
}

function downloadFile(url, destination) {
  return new Promise((resolve, reject) => {
    console.log(`Downloading from: ${url}`);

    // Follow redirects
    const download = (url, redirectCount = 0) => {
      if (redirectCount > 5) {
        reject(new Error('Too many redirects'));
        return;
      }

      https.get(url, (response) => {
        if (response.statusCode === 301 || response.statusCode === 302) {
          console.log(`Following redirect to: ${response.headers.location}`);
          download(response.headers.location, redirectCount + 1);
          return;
        }

        if (response.statusCode !== 200) {
          reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
          return;
        }

        const totalSize = parseInt(response.headers['content-length'], 10);
        let downloadedSize = 0;
        let lastProgress = 0;

        response.on('data', (chunk) => {
          downloadedSize += chunk.length;
          const progress = Math.round((downloadedSize / totalSize) * 100);

          // Only log every 10% to reduce noise
          if (progress >= lastProgress + 10) {
            console.log(`Download progress: ${progress}%`);
            lastProgress = progress;
          }
        });

        const file = createWriteStream(destination);

        pipeline(response, file, (err) => {
          if (err) {
            reject(err);
          } else {
            console.log('Download complete!');
            resolve();
          }
        });
      }).on('error', reject);
    };

    download(url);
  });
}

async function main() {
  console.log('===========================================');
  console.log('  MAILER - Binary Installation');
  console.log('===========================================');
  console.log('');

  const binaryInfo = getBinaryInfo();

  if (!binaryInfo.supported) {
    console.error(`❌ Error: Unsupported platform/architecture: ${binaryInfo.platform}/${binaryInfo.arch}`);
    console.error('');
    console.error('Supported platforms:');
    console.error('  • Linux (x64, arm64)');
    console.error('  • macOS (x64, arm64)');
    console.error('  • Windows (x64)');
    console.error('');
    console.error('If you believe your platform should be supported, please file an issue:');
    console.error('  https://code.foss.global/serve.zone/mailer/issues');
    process.exit(1);
  }

  console.log(`Platform: ${binaryInfo.platform} (${binaryInfo.originalPlatform})`);
  console.log(`Architecture: ${binaryInfo.arch}`);
  console.log(`Binary: ${binaryInfo.binaryName}`);
  console.log(`Version: ${VERSION}`);
  console.log('');

  // Create dist/binaries directory if it doesn't exist
  const binariesDir = join(__dirname, '..', 'dist', 'binaries');
  if (!existsSync(binariesDir)) {
    console.log('Creating binaries directory...');
    mkdirSync(binariesDir, { recursive: true });
  }

  const binaryPath = join(binariesDir, binaryInfo.binaryName);

  // Check if binary already exists and skip download
  if (existsSync(binaryPath)) {
    console.log('✓ Binary already exists, skipping download');
  } else {
    // Construct download URL
    // Try release URL first, fall back to raw branch if needed
    const releaseUrl = `${REPO_BASE}/releases/download/v${VERSION}/${binaryInfo.binaryName}`;
    const fallbackUrl = `${REPO_BASE}/raw/branch/main/dist/binaries/${binaryInfo.binaryName}`;

    console.log('Downloading platform-specific binary...');
    console.log('This may take a moment depending on your connection speed.');
    console.log('');

    try {
      // Try downloading from release
      await downloadFile(releaseUrl, binaryPath);
    } catch (err) {
      console.log(`Release download failed: ${err.message}`);
      console.log('Trying fallback URL...');

      try {
        // Try fallback URL
        await downloadFile(fallbackUrl, binaryPath);
      } catch (fallbackErr) {
        console.error(`❌ Error: Failed to download binary`);
        console.error(`  Primary URL: ${releaseUrl}`);
        console.error(`  Fallback URL: ${fallbackUrl}`);
        console.error('');
        console.error('This might be because:');
        console.error('1. The release has not been created yet');
        console.error('2. Network connectivity issues');
        console.error('3. The version specified does not exist');
        console.error('');
        console.error('You can try:');
        console.error('1. Installing from source: https://code.foss.global/serve.zone/mailer');
        console.error('2. Downloading the binary manually from the releases page');

        // Clean up partial download
        if (existsSync(binaryPath)) {
          unlinkSync(binaryPath);
        }

        process.exit(1);
      }
    }

    console.log(`✓ Binary downloaded successfully`);
  }

  // On Unix-like systems, ensure the binary is executable
  if (binaryInfo.originalPlatform !== 'win32') {
    try {
      console.log('Setting executable permissions...');
      chmodSync(binaryPath, 0o755);
      console.log('✓ Binary permissions updated');
    } catch (err) {
      console.error(`⚠️  Warning: Could not set executable permissions: ${err.message}`);
      console.error('   You may need to manually run:');
      console.error(`   chmod +x ${binaryPath}`);
    }
  }

  console.log('');
  console.log('✅ MAILER installation completed successfully!');
  console.log('');
  console.log('You can now use MAILER by running:');
  console.log('  mailer --help');
  console.log('');
  console.log('For initial setup, run:');
  console.log('  sudo mailer service enable');
  console.log('');
  console.log('===========================================');
}

// Run the installation
main().catch(err => {
  console.error(`❌ Installation failed: ${err.message}`);
  process.exit(1);
});
