import { NativeModule, requireNativeModule } from 'expo';

import type {
  ActivateResult,
  DeviceLayers,
  DisableResult,
  HealthProbeOpts,
  HealthProbeResult,
  RebreakProtectionEvents,
  SyncBlocklistOpts,
  SyncBlocklistResult,
  SystemSettingsTarget,
} from './RebreakProtection.types';

declare class RebreakProtectionModule extends NativeModule<RebreakProtectionEvents> {
  /**
   * iOS: aktiviert NUR den NEFilter (URL-Filter Layer).
   * Triggert iOS-Dialog "Filter-Konfiguration zulassen".
   */
  activateUrlFilter(): Promise<{ enabled: boolean; error?: string }>;

  /**
   * iOS: nach "Nicht erlauben" beim NEFilter-Permission-Dialog hat iOS den
   * Denied-State gecached und zeigt beim erneuten activateUrlFilter() den
   * Dialog nicht mehr (code 5 silent). resetUrlFilter() macht ein
   * removeFromPreferences vor dem saveToPreferences — iOS behandelt das als
   * brandneuen Permission-Request → frischer System-Dialog.
   *
   * Nicht aufrufen wenn der User schon einmal "Erlauben" getippt hat — dann
   * würde ein unnötiger Dialog kommen. Nur als Workaround bei code 5 nutzen.
   */
  resetUrlFilter(): Promise<{ enabled: boolean; error?: string }>;

  /**
   * iOS: aktiviert NUR Family Controls (Auth + denyAppRemoval = der Lock).
   * Triggert iOS-Dialog "Bildschirmzeit verwalten".
   * Sobald aktiv, kann der User den Schutz nur über Cooldown deaktivieren.
   */
  activateFamilyControls(): Promise<{ enabled: boolean; error?: string }>;

  /**
   * Aktiviert ALLE Schutz-Layer in einem Call (legacy, beide Dialoge nacheinander).
   * Bevorzugt activateUrlFilter() + activateFamilyControls() einzeln aufrufen.
   */
  activate(): Promise<ActivateResult>;

  /**
   * Schaltet ALLE Schutz-Layer ab. NUR aufrufen wenn JS-Layer verifiziert
   * hat dass der 24h-Cooldown abgelaufen ist. Native-Modul prüft das nicht
   * — der Backend-Cooldown ist Single Source of Truth, das ist Aufgabe der
   * JS-Schicht.
   */
  disable(): Promise<DisableResult>;

  /** Aktueller Device-State. Polling- und Health-Check-Pfad. */
  getDeviceState(): Promise<DeviceLayers>;

  /**
   * Lädt blocklist.bin vom Server, schreibt atomisch in App-Group/internal
   * storage, postet Reload-Notification an die Filter-Extension. Server
   * respondet 304 wenn ETag matched → updated=false. Plan-aware:
   * Free → nur personal-domains (≤5), Pro/Legend → 208k+ + personal.
   */
  syncBlocklist(opts: SyncBlocklistOpts): Promise<SyncBlocklistResult>;

  /**
   * E2E-Verifikation: Hidden WebView lädt eine bekannte Gambling-Domain,
   * prüft ob WebKit/Browser den Load aborted (Filter funktioniert) oder die
   * Page lädt (Filter ist tot — Alarm).
   */
  runHealthProbe(opts?: HealthProbeOpts): Promise<HealthProbeResult>;

  /** Öffnet System-Settings auf dem entsprechenden Tab. */
  openSystemSettings(target?: SystemSettingsTarget): Promise<void>;

  // ─── Android-spezifische Methoden (auf iOS undefined zur Laufzeit) ───────

  /** Android: Live-Check ob unser AccessibilityService aktuell als enabled
   *  registriert ist (Settings.Secure + AccessibilityManager). */
  isAccessibilityEnabled(): Promise<{ enabled: boolean }>;

  /** Android: Öffnet Settings → Bedienungshilfen, möglichst tief auf die
   *  Rebreak-Detail-Page (deep-link). Fallback: generelle A11y-Liste. */
  openAccessibilitySettings(): Promise<{ opened: boolean }>;

  /** Android: Aktiviert Tamper-Lock-Watchdog (Settings-Page-Blockade durch
   *  AccessibilityService). Wirft `preconditions_not_met` wenn VPN oder A11y
   *  nicht beide live. */
  armTamperLock(): Promise<{ armed: boolean }>;

  /** Android: Disarm Tamper-Lock. Schutz-Layers laufen weiter, aber Settings-
   *  Watchdog blockt nicht mehr. Im normalen Flow nur nach Cooldown-Ablauf. */
  disarmTamperLock(): Promise<{ armed: boolean }>;

  /** Android: kombinierter Status aller 3 Layers + Blocklist-Count. */
  getProtectionStatus(): Promise<{
    vpnEnabled: boolean;
    accessibilityEnabled: boolean;
    blocklistCount: number;
    tamperArmed: boolean;
  }>;

  /** Android: Wenn der Schutz an sein soll (`filter_enabled`) der VpnService
   *  aber nicht läuft (Reinstall / Low-Mem-Kill) → neu starten. Bei App-Start /
   *  Foreground aufrufen, damit der State nicht „an aber tot" bleibt. */
  reconcileVpn(): Promise<{ restarted: boolean; needsConsent?: boolean }>;
}

export default requireNativeModule<RebreakProtectionModule>('RebreakProtection');
