/**
 * PP-OCRv5 (ONNX Runtime) Config Plugin（plan.md「决策 4 Expo Config Plugin 方案」+「3.4 Layer 2」）。
 *
 * 本插件在 expo prebuild 时：
 * 1. 复制 Kotlin 源码（OcrModule.kt + OcrPackage.kt）到 android/app/src/main/java/...
 * 2. 复制 ONNX 模型与字典到 android/app/src/main/assets
 * 3. 注册 OcrPackage 到 MainApplication（getPackages）
 * 4. 添加 onnxruntime-android 依赖（app/build.gradle）
 *
 * 引擎：ONNX Runtime（跨平台、微软官方、Windows 友好），替代 NCNN 路线。
 * 注意：SDK 54 的 @expo/config-plugins 暴露的是 withMainApplication / withAppBuildGradle
 * （没有 withAndroidMainApplication / withAndroidGradle）。文件复制用 withDangerousMod。
 *
 * 模型文件放 plugins/ppocr/assets/，版权/体积原因不入仓库，需自行下载（见 README.md）。
 */

const {
  withMainApplication,
  withAppBuildGradle,
  withDangerousMod,
} = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

function getAppId(config) {
  return config.android?.package || 'com.example.driftledger';
}

/** 递归复制目录，prebuild 阶段执行并替换包名。 */
function copyAndReplaceDir(src, dest, appId) {
  if (!fs.existsSync(src)) return;
  fs.mkdirSync(dest, { recursive: true });
  for (const entry of fs.readdirSync(src)) {
    const s = path.join(src, entry);
    const d = path.join(dest, entry);
    if (fs.statSync(s).isDirectory()) {
      copyAndReplaceDir(s, d, appId);
    } else {
      if (entry.endsWith('.kt') || entry.endsWith('.java')) {
        let content = fs.readFileSync(s, 'utf8');
        content = content.replace(/package\s+com\.beancount\.mobile/g, `package ${appId}`);
        content = content.replace(/import\s+com\.beancount\.mobile/g, `import ${appId}`);
        fs.writeFileSync(d, content, 'utf8');
      } else {
        fs.copyFileSync(s, d);
      }
    }
  }
}

/** 递归复制目录（仅用于模型资源复制，不替换包名）。 */
function copyDir(src, dest) {
  if (!fs.existsSync(src)) return;
  fs.mkdirSync(dest, { recursive: true });
  for (const entry of fs.readdirSync(src)) {
    const s = path.join(src, entry);
    const d = path.join(dest, entry);
    if (fs.statSync(s).isDirectory()) copyDir(s, d);
    else fs.copyFileSync(s, d);
  }
}

function withPpOcr(config) {
  const appId = getAppId(config);
  const PACKAGE = `${appId}.ppocr`;

  // 1+2. 复制 Kotlin 源码与 ONNX 模型/字典到原生工程
  config = withDangerousMod(config, [
    'android',
    async (modConfig) => {
      const projectRoot = modConfig.modRequest.platformProjectRoot;
      const pkgPath = appId.replace(/\./g, '/');
      const ktDest = path.join(projectRoot, 'app/src/main/java', pkgPath, 'ppocr');

      // Kotlin 源码并自动重命名包名
      copyAndReplaceDir(
        path.join(__dirname, 'android'),
        ktDest,
        appId,
      );

      // ONNX 模型 + 字典（若已下载）
      const assetsSrc = path.join(__dirname, 'assets');
      if (fs.existsSync(assetsSrc)) {
        copyDir(
          assetsSrc,
          path.join(projectRoot, 'app/src/main/assets'),
        );
      }
      return modConfig;
    },
  ]);

  // 3. 注册 OcrPackage 到 MainApplication
  config = withMainApplication(config, (modConfig) => {
    let content = modConfig.modResults.contents;

    // 3a. 注入 import（在 package 声明行后插入）
    content = content.replace(/^import\s+[\w.]+\.OcrPackage\s*$/gm, '');
    content = content.replace(
      /^(package\s+[\w.]+;?\s*)$/m,
      `$1\nimport ${PACKAGE}.OcrPackage`,
    );

    // 3b. 在 getPackages() 的 .apply {} 块里注入 add(OcrPackage())
    if (!content.includes('add(OcrPackage())')) {
      if (/PackageList\(this\)\.packages\.apply\s*\{/.test(content)) {
        // 新架构 Kotlin（SDK 54 默认）：模板已有空 .apply {} 块，在块开头注入
        content = content.replace(
          /(PackageList\(this\)\.packages\.apply\s*\{)/,
          `$1\n              // PP-OCRv5 ONNX 原生模块（由 Config Plugin 注入）\n              add(OcrPackage())`,
        );
      } else if (/PackageList\(this\)\.packages\b/.test(content)) {
        // 新架构变体：.packages 后没有 .apply，包一层
        content = content.replace(
          /PackageList\(this\)\.packages\b/,
          `PackageList(this).packages.apply { add(OcrPackage()) }`,
        );
      } else if (/\breturn\s+packages\s*;/.test(content)) {
        // 老架构 Java：在 return packages; 前插入
        content = content.replace(
          /(\breturn\s+packages\s*;)/,
          `packages.add(new OcrPackage());\n      $1`,
        );
      }
    }

    modConfig.modResults.contents = content;
    return modConfig;
  });

  // 4. 配置 app/build.gradle 依赖（ONNX Runtime Android）
  config = withAppBuildGradle(config, (modConfig) => {
    let gradle = modConfig.modResults.contents;
    if (!gradle.includes('onnxruntime')) {
      // 在 dependencies { 开头处插入，避免嵌套花括号的正则匹配错误
      gradle = gradle.replace(
        /(dependencies\s*\{)/,
        `$1\n    // PP-OCRv5 ONNX Runtime（由 Config Plugin 注入）\n    implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.20.0'`
      );
    }
    modConfig.modResults.contents = gradle;
    return modConfig;
  });

  return config;
}

module.exports = withPpOcr;
