/* eslint-disable @typescript-eslint/no-var-requires */
/**
 * Expo Config-Plugin — wires the Android VpnService (DNS-Filter) +
 * AccessibilityService (URL filter Layer 2) into AndroidManifest.xml at
 * prebuild time.
 *
 * Was es macht:
 *   1) Sorgt für `xmlns:tools` auf <manifest>.
 *   2) Registriert <service .RebreakVpnService> mit
 *      foregroundServiceType="systemExempted" + intent-filter
 *      android.net.VpnService + permission BIND_VPN_SERVICE.
 *      (`systemExempted` ist seit Android 14 der korrekte Type für
 *      VPN-/Filter-Foreground-Services — vorher war `specialUse`+content_filter
 *      angedacht aber bringt mehr Probleme als Nutzen.)
 *   3) Registriert <service .RebreakAccessibilityService> mit
 *      android:permission=BIND_ACCESSIBILITY_SERVICE + intent-filter
 *      android.accessibilityservice.AccessibilityService + meta-data
 *      android.accessibilityservice → @xml/accessibility_service_config.
 *
 * Wird aus app.config.ts via `plugins: ['./plugins/with-rebreak-protection-android']`
 * registriert. Idempotent — kann beliebig oft via `expo prebuild` laufen.
 *
 * Native Source: `modules/rebreak-protection/android/src/main/java/expo/modules/rebreakprotection/`
 *  - VpnService:           expo.modules.rebreakprotection.vpn.RebreakVpnService
 *  - AccessibilityService: expo.modules.rebreakprotection.accessibility.RebreakAccessibilityService
 */

const {
  withAndroidManifest,
  withStringsXml,
  withDangerousMod,
  AndroidConfig,
} = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

const VPN_SERVICE_CLASS =
  'expo.modules.rebreakprotection.vpn.RebreakVpnService';
const A11Y_SERVICE_CLASS =
  'expo.modules.rebreakprotection.accessibility.RebreakAccessibilityService';

// ─── 1) tools-Namespace auf <manifest> ──────────────────────────────────────

function ensureToolsNamespace(manifest) {
  if (!manifest.manifest.$) manifest.manifest.$ = {};
  if (!manifest.manifest.$['xmlns:tools']) {
    manifest.manifest.$['xmlns:tools'] = 'http://schemas.android.com/tools';
  }
}

// ─── 2) <service>-Tag für RebreakVpnService ─────────────────────────────────

function ensureVpnService(manifest) {
  const application = AndroidConfig.Manifest.getMainApplicationOrThrow(manifest);

  if (!application.service) application.service = [];

  const alreadyDeclared = application.service.some(
    (svc) => svc.$ && svc.$['android:name'] === VPN_SERVICE_CLASS,
  );
  if (alreadyDeclared) return;

  application.service.push({
    $: {
      'android:name': VPN_SERVICE_CLASS,
      'android:permission': 'android.permission.BIND_VPN_SERVICE',
      'android:foregroundServiceType': 'systemExempted',
      'android:exported': 'false',
    },
    'intent-filter': [
      {
        action: [{ $: { 'android:name': 'android.net.VpnService' } }],
      },
    ],
  });
}

// ─── 3) <service>-Tag für RebreakAccessibilityService ───────────────────────

function ensureAccessibilityService(manifest) {
  const application = AndroidConfig.Manifest.getMainApplicationOrThrow(manifest);

  if (!application.service) application.service = [];

  const alreadyDeclared = application.service.some(
    (svc) => svc.$ && svc.$['android:name'] === A11Y_SERVICE_CLASS,
  );
  if (alreadyDeclared) return;

  application.service.push({
    $: {
      'android:name': A11Y_SERVICE_CLASS,
      'android:permission': 'android.permission.BIND_ACCESSIBILITY_SERVICE',
      'android:label': '@string/accessibility_service_summary',
      'android:exported': 'true',
    },
    'intent-filter': [
      {
        action: [
          {
            $: {
              'android:name':
                'android.accessibilityservice.AccessibilityService',
            },
          },
        ],
      },
    ],
    'meta-data': [
      {
        $: {
          'android:name': 'android.accessibilityservice',
          'android:resource': '@xml/accessibility_service_config',
        },
      },
    ],
  });
}

// ─── 4) String resources für a11y-service ───────────────────────────────────

const A11Y_DESCRIPTION_TEXT =
  'Sichert deinen Schutz gegen impulsives Abschalten ab: Solange App-Lock aktiv ist, kann das ReBreak-VPN nicht in den Einstellungen deaktiviert und die App nicht deinstalliert werden. Das Blockieren von Glücksspielseiten selbst übernimmt das VPN — diese Berechtigung sichert es nur. Du kannst den Schutz jederzeit über die Abkühlphase in der App beenden.';
const A11Y_SUMMARY_TEXT =
  'Sichert den Schutz gegen Abschalten ab';

function withA11yStringResource(config) {
  return withStringsXml(config, (cfg) => {
    cfg.modResults = AndroidConfig.Strings.setStringItem(
      [
        {
          $: { name: 'accessibility_service_description', translatable: 'false' },
          _: A11Y_DESCRIPTION_TEXT,
        },
      ],
      cfg.modResults,
    );
    cfg.modResults = AndroidConfig.Strings.setStringItem(
      [
        {
          $: { name: 'accessibility_service_summary', translatable: 'false' },
          _: A11Y_SUMMARY_TEXT,
        },
      ],
      cfg.modResults,
    );
    return cfg;
  });
}

// ─── 5) XML-config für AccessibilityService ─────────────────────────────────
// Kopiert die Source-of-Truth aus dem Modul-Verzeichnis statt einen
// hardcoded String zu pflegen — so bleibt Plugin + Service-Config immer sync.

const MODULE_A11Y_XML = path.resolve(
  __dirname,
  '../modules/rebreak-protection/android/src/main/res/xml/accessibility_service_config.xml',
);

function withA11yConfigXml(config) {
  return withDangerousMod(config, [
    'android',
    async (cfg) => {
      const xmlDir = path.join(
        cfg.modRequest.platformProjectRoot,
        'app/src/main/res/xml',
      );
      fs.mkdirSync(xmlDir, { recursive: true });
      fs.copyFileSync(
        MODULE_A11Y_XML,
        path.join(xmlDir, 'accessibility_service_config.xml'),
      );
      return cfg;
    },
  ]);
}

// ─── Composition ────────────────────────────────────────────────────────────

function withRebreakProtectionAndroid(config) {
  config = withAndroidManifest(config, (cfg) => {
    ensureToolsNamespace(cfg.modResults);
    ensureVpnService(cfg.modResults);
    ensureAccessibilityService(cfg.modResults);
    return cfg;
  });
  config = withA11yStringResource(config);
  config = withA11yConfigXml(config);
  return config;
}

module.exports = withRebreakProtectionAndroid;
