const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

// 定义项目根目录
const rootDir = __dirname;
// 定义输出目录
const distDir = path.join(rootDir, 'dist');
// 定义要排除的目录和文件
const excludeDirs = ['node_modules', '.git', 'dist', '.vscode'];
const excludeFiles = ['.gitignore', 'package-lock.json', 'yarn.lock', 'release.js', 'README.md'];

// 获取当前日期，用于生成zip文件名（格式：YYYY-MM-DD）
function getCurrentDate() {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

// 定义wxml压缩函数
function compressWxml(content) {
  // 移除HTML注释
  content = content.replace(/<!--[\s\S]*?-->/g, '');
  
  // 移除多余的空白字符（空格、换行、制表符）
  // 保留标签内的必要空格
  content = content.replace(/\s+/g, ' ');
  
  // 移除标签前后的空格
  content = content.replace(/\s*</g, '<');
  content = content.replace(/>\s*/g, '>');
  
  return content;
}

// 定义js压缩函数 - 采用更安全的压缩策略，接近微信小程序开发工具的压缩方式
function compressJs(content) {
  // 移除单行注释
  content = content.replace(/\/\/.*$/gm, '');
  
  // 移除多行注释
  content = content.replace(/\/\*[\s\S]*?\*\//g, '');
  
  // 移除行尾多余的空白字符
  content = content.replace(/\s+$/gm, '');
  
  // 移除多余的空行，只保留必要的换行
  content = content.replace(/\n{2,}/g, '\n');
  
  // 保存所有require语句，避免压缩时破坏模块路径
  const requireStatements = [];
  let requireIndex = 0;
  content = content.replace(/require\s*\([^)]+\)/g, (match) => {
    const placeholder = `__REQUIRE_PLACEHOLDER_${requireIndex}__`;
    requireStatements.push({ placeholder, content: match });
    requireIndex++;
    return placeholder;
  });
  
  // 在适当的位置添加分号，避免语法错误
  // 只在特定情况下添加分号
  // 1. 处理return、break、continue、throw等语句
  content = content.replace(/(return|break|continue|throw)\s*(.*?)\n/g, '$1 $2;\n');
  // 2. 处理变量声明和赋值（简单情况）
  content = content.replace(/([a-zA-Z_$][a-zA-Z0-9_$]*\s*=\s*[^;\n]+)\n/g, '$1;\n');
  // 3. 处理函数调用
  content = content.replace(/([a-zA-Z_$][a-zA-Z0-9_$]*\s*\([^;\n]+\))\n/g, '$1;\n');
  
  // 移除语句之间多余的空白字符，但保留必要的空格
  content = content.replace(/\s*\{\s*/g, '{');
  content = content.replace(/\s*\}\s*/g, '}');
  content = content.replace(/\s*;\s*/g, ';');
  content = content.replace(/\s*,\s*/g, ',');
  content = content.replace(/\s*=\s*/g, '=');
  content = content.replace(/\s*\+\s*/g, '+');
  content = content.replace(/\s*-\s*/g, '-');
  content = content.replace(/\s*\*\s*/g, '*');
  content = content.replace(/\s*\/\s*/g, '/');
  content = content.replace(/\s*\[\s*/g, '[');
  content = content.replace(/\s*\]\s*/g, ']');
  
  // 移除多余的分号
  content = content.replace(/;;+/g, ';');
  
  // 移除多余的空白字符（连续的空格只保留一个）
  content = content.replace(/\s+/g, ' ');
  
  // 恢复之前保存的require语句
  requireStatements.forEach(({ placeholder, content: requireContent }) => {
    content = content.replace(placeholder, requireContent + ';');
  });
  
  // 移除文件开头和结尾的分号
  content = content.replace(/^;|;$/g, '');
  
  // 移除所有多余的空格
  content = content.replace(/\s+/g, '');
  
  // 确保最后一个require语句也有分号
  content = content.replace(/require\([^)]+\)$/, '$&;');
  
  return content;
}

// 定义css压缩函数
function compressCss(content) {
  // 移除单行注释
  content = content.replace(/\/\/.*$/gm, '');
  
  // 移除多行注释
  content = content.replace(/\/\*[\s\S]*?\*\//g, '');
  
  // 移除多余的空白字符
  content = content.replace(/\s+/g, ' ');
  
  // 移除CSS属性前后的空格
  content = content.replace(/\s*([{:;}])\s*/g, '$1');
  
  // 移除行首和行尾的空格
  content = content.replace(/^\s+|\s+$/gm, '');
  
  return content;
}

// 定义json压缩函数
function compressJson(content) {
  try {
    // 使用JSON.parse和JSON.stringify进行压缩
    // 确保中文等非ASCII字符不会被转义
    const jsonObj = JSON.parse(content);
    return JSON.stringify(jsonObj, null, 0);
  } catch (error) {
    // 如果JSON解析失败，返回原始内容
    console.warn('Failed to compress JSON, using original content:', error.message);
    return content;
  }
}

// 递归复制目录并压缩文件（wxml, js, css, json）
function copyAndCompressDir(sourceDir, targetDir) {
  // 创建目标目录
  if (!fs.existsSync(targetDir)) {
    fs.mkdirSync(targetDir, { recursive: true });
  }
  
  const files = fs.readdirSync(sourceDir);
  
  files.forEach(file => {
    const sourcePath = path.join(sourceDir, file);
    const targetPath = path.join(targetDir, file);
    const stats = fs.statSync(sourcePath);
    
    // 跳过排除的目录和文件
    if (excludeDirs.includes(file) || excludeFiles.includes(file)) {
      return;
    }
    
    if (stats.isDirectory()) {
      // 递归处理子目录
      copyAndCompressDir(sourcePath, targetPath);
    } else {
      const extname = path.extname(file);
      let compressedContent;
      let content;
      
      try {
        // 根据文件类型选择不同的处理方式
        if (extname === '.wxml') {
          // 压缩wxml文件
          content = fs.readFileSync(sourcePath, { encoding: 'utf8' });
          compressedContent = compressWxml(content);
          fs.writeFileSync(targetPath, compressedContent, { encoding: 'utf8' });
          console.log(`Compressed and copied: ${sourcePath}`);
        } else if (extname === '.js') {
          // 压缩js文件, 还是有问题，会出现编译错误。暂时不适用压缩
          content = fs.readFileSync(sourcePath, { encoding: 'utf8' });
          // compressedContent = compressJs(content);
          fs.writeFileSync(targetPath, content, { encoding: 'utf8' });
          console.log(`Compressed and copied: ${sourcePath}`);
        } else if (extname === '.css') {
          // 压缩css文件
          content = fs.readFileSync(sourcePath, { encoding: 'utf8' });
          compressedContent = compressCss(content);
          fs.writeFileSync(targetPath, compressedContent, { encoding: 'utf8' });
          console.log(`Compressed and copied: ${sourcePath}`);
        } else if (extname === '.json') {
          // 压缩json文件
          content = fs.readFileSync(sourcePath, { encoding: 'utf8' });
          compressedContent = compressJson(content);
          fs.writeFileSync(targetPath, compressedContent, { encoding: 'utf8' });
          console.log(`Compressed and copied: ${sourcePath}`);
        } else {
          // 直接复制其他文件
          fs.copyFileSync(sourcePath, targetPath);
          console.log(`Copied: ${sourcePath}`);
        }
      } catch (error) {
        console.error(`Error processing file ${sourcePath}:`, error.message);
        // 发生错误时，直接复制原始文件
        fs.copyFileSync(sourcePath, targetPath);
        console.log(`Fallback: Copied original file ${sourcePath}`);
      }
    }
  });
}

// 使用系统命令创建zip压缩包
function createZipArchive(sourceDir, outputPath) {
  try {
    // 根据操作系统选择命令
    if (process.platform === 'win32') {
      // Windows系统使用PowerShell命令，排除文件名后缀为 -mp-weixin.zip 的文件
      // 使用PowerShell的管道功能和Where-Object来排除特定文件
      const command = `PowerShell.exe -Command "Get-ChildItem -Path \"${sourceDir}\" | Where-Object { $_.Name -notlike '*\-mp\-weixin\.zip' } | Compress-Archive -DestinationPath \"${outputPath}\" -Force"`;
      execSync(command, { shell: 'cmd.exe' });
    } else {
      // Linux/Mac系统使用zip命令，排除文件名后缀为 -mp-weixin.zip 的文件
      const command = `zip -r "${outputPath}" * -x "*-mp-weixin.zip"`;
      execSync(command, { cwd: sourceDir });
    }
    console.log(`Zip archive created: ${outputPath}`);
  } catch (error) {
    console.error('Error creating zip archive:', error.message);
    throw error;
  }
}

function cleanDistDir(distDir) {
  if (fs.existsSync(distDir)) {
      // 清理dist目录下除**-mp-weixin.zip文件外的所有内容
      const files = fs.readdirSync(distDir);
      files.forEach(file => {
        const filePath = path.join(distDir, file);
        const stats = fs.statSync(filePath);
        
        // 只保留符合特定命名模式的zip文件（**-mp-weixin.zip）
        if (stats.isFile() && path.extname(file) === '.zip' && file.endsWith('-mp-weixin.zip')) {
          console.log(`Keeping zip file: ${file}`);
        } else {
          if (stats.isDirectory()) {
            fs.rmSync(filePath, { recursive: true, force: true });
            console.log(`Removed directory: ${file}`);
          } else {
            fs.unlinkSync(filePath);
            console.log(`Removed file: ${file}`);
          }
        }
      });
      console.log('Cleaned dist directory (excluding -mp-weixin.zip files)');
  }
}

// 主函数
function main() {
  try {
    // 解析命令行参数
    const args = process.argv.slice(2);
    const keepDist = args.includes('--keep-dist') || args.includes('-k');
    
    // 清理dist目录（如果存在且不保留）
    if (fs.existsSync(distDir)) {
      cleanDistDir(distDir);
    } else {
      // 创建dist目录
      fs.mkdirSync(distDir, { recursive: true });
      console.log('Created dist directory');
    }
    
    // 复制并压缩文件到dist目录
    console.log('Start copying and compressing files...');
    copyAndCompressDir(rootDir, distDir);
    console.log('Files copied and compressed successfully!');
    
    // 生成zip文件名（格式：POCT检测分析平台-定制化-YYYY-MM-DD-mp-weixin.zip）
    const currentDate = getCurrentDate();
    const zipFileName = `POCT检测分析平台-定制化-${currentDate}-mp-weixin.zip`;
    const zipPath = path.join(distDir, zipFileName);
    
    // 创建zip压缩包
    console.log('Creating zip archive...');
    createZipArchive(distDir, zipPath);

    // 清理dist目录（如果不保留）
    if (!keepDist) {
      cleanDistDir(distDir);
    }
    
    console.log('\nAll tasks completed successfully!');
    console.log(`Dist directory: ${distDir}`);
    console.log(`Zip file: ${zipPath}`);
  } catch (error) {
    console.error('Error occurred:', error);
    process.exit(1);
  }
}

// 执行主函数
main();

// 输出帮助信息
if (process.argv.includes('--help') || process.argv.includes('-h')) {
  console.log('Usage: node release.js [options]');
  console.log('Options:');
  console.log('  --keep-dist, -k    Keep existing dist directory contents');
  console.log('  --help, -h         Show this help message');
}