import { TurboModuleRegistry } from 'react-native';

import type { TurboModule } from 'react-native';

// eslint-disable-next-line @typescript-eslint/naming-convention
export interface Spec extends TurboModule {
  // WebAPI configuration and token management
  setApiUrl(url: string): Promise<void>;
  getApiUrl(): Promise<string>;
  setAuthTokens(accessToken: string, refreshToken: string): Promise<void>;
  getAccessToken(): Promise<string | null>;
  clearAuthTokens(): Promise<void>;
  revokeTokens(): Promise<void>;
  // Custom proxy headers added to every outgoing API request
  setCustomProxyHeaders(headersJson: string): Promise<void>;
  getCustomProxyHeaders(): Promise<string>;

  // WebAPI request execution
  executeWebApiRequest(method: string, endpoint: string, body: string | null, headers: string, requiresAuth: boolean): Promise<string>;

  // Vault state management
  isVaultUnlocked(): Promise<boolean>;
  getVaultMetadata(): Promise<string>;
  unlockVault(): Promise<boolean>;
  clearSession(): Promise<void>;  // Clears session only, preserves vault for potential RPO recovery
  clearVault(): Promise<void>;    // Clears everything including vault data

  // Vault sync
  syncVaultWithServer(): Promise<{ success: boolean; action: 'uploaded' | 'downloaded' | 'merged' | 'already_in_sync' | 'error'; newRevision: number; wasOffline: boolean; error: string | null }>;

  // Quick check if sync is needed
  checkSyncStatus(): Promise<{ success: boolean; hasNewerVault: boolean; hasDirtyChanges: boolean; isOffline: boolean; requiresLogout: boolean; errorKey: string | null }>;

  // Sync state management
  getSyncState(): Promise<{isDirty: boolean; mutationSequence: number; serverRevision: number; isSyncing: boolean}>;
  markVaultClean(mutationSeqAtStart: number, newServerRevision: number): Promise<boolean>;
  clearEncryptedVaultForFreshDownload(): Promise<void>;

  // Vault SQL operations
  executeQuery(query: string, params: (string | number | null)[]): Promise<string[]>;
  executeUpdate(query: string, params:(string | number | null)[]): Promise<number>;
  executeRaw(query: string): Promise<void>;
  beginTransaction(): Promise<void>;
  commitTransaction(): Promise<void>;
  rollbackTransaction(): Promise<void>;
  // Persist the in-memory database to encrypted storage and mark as dirty
  persistAndMarkDirty(): Promise<void>;

  // Cryptography operations
  deriveKeyFromPassword(password: string, salt: string, encryptionType: string, encryptionSettings: string): Promise<string>;

  // Database/encryption key operations
  storeMetadata(metadata: string): Promise<void>;
  setAuthMethods(authMethods: string[]): Promise<void>;
  storeEncryptionKeyInMemory(base64EncryptionKey: string): Promise<void>;
  clearEncryptionKeyFromMemory(): Promise<void>;
  storeEncryptionKey(base64EncryptionKey: string): Promise<void>;
  storeEncryptionKeyDerivationParams(keyDerivationParams: string): Promise<void>;
  getEncryptionKeyDerivationParams(): Promise<string | null>;
  hasEncryptedDatabase(): Promise<boolean>;
  getEncryptedDatabase(): Promise<string | null>;

  // Auto-lock settings
  setAutoLockTimeout(timeout: number): Promise<void>;
  getAutoLockTimeout(): Promise<number>;
  getAuthMethods(): Promise<string[]>;
  openAutofillSettingsPage(): Promise<void>;
  getAutofillShowSearchText(): Promise<boolean>;
  setAutofillShowSearchText(showSearchText: boolean): Promise<void>;
  getAutofillCopyTotpOnFill(): Promise<boolean>;
  setAutofillCopyTotpOnFill(enabled: boolean): Promise<void>;

  // Clipboard management
  copyToClipboardWithExpiration(text: string, expirationSeconds: number, localOnly: boolean): Promise<void>;

  // TOTP code generation (RFC 6238, HMAC-SHA1, 6 digits, 30s period).
  // Delegates to the platform-native TOTP generator so iOS, Android and the
  // autofill extensions all share one implementation. Returns null when the
  // secret is invalid.
  generateTotpCode(secret: string): Promise<string | null>;

  // Battery optimization management
  isIgnoringBatteryOptimizations(): Promise<boolean>;
  requestIgnoreBatteryOptimizations(): Promise<string>;

  // Credential identity management
  registerCredentialIdentities(): Promise<void>;
  removeCredentialIdentities(): Promise<void>;

  // Username management
  setUsername(username: string): Promise<void>;
  getUsername(): Promise<string | null>;
  clearUsername(): Promise<void>;

  // Offline mode management
  setOfflineMode(isOffline: boolean): Promise<void>;
  getOfflineMode(): Promise<boolean>;

  // Server version management
  isServerVersionGreaterThanOrEqualTo(targetVersion: string): Promise<boolean>;
  getServerVersion(): Promise<string | null>;

  // PIN unlock methods
  isPinEnabled(): Promise<boolean>;
  isKeystoreAvailable(): Promise<boolean>;

  // Biometric unlock validation - checks if biometric unlock is actually available
  // Returns true only if device supports biometrics AND the encryption key is valid
  // Returns false if key has been invalidated (e.g., biometric enrollment changed)
  isBiometricUnlockAvailable(): Promise<boolean>;

  removeAndDisablePin(): Promise<void>;
  showPinUnlock(): Promise<void>;
  showPinSetup(): Promise<void>;

  // Password unlock method. Shows native password unlock screen.
  // Returns true if successful, null if cancelled.
  // If title/subtitle are null/empty, defaults to "Unlock Vault" context.
  // If buttonText is null/empty, defaults to "Unlock".
  showPasswordUnlock(title: string | null, subtitle: string | null, buttonText: string | null): Promise<boolean | null>;

  // Mobile login methods
  encryptDecryptionKeyForMobileLogin(publicKeyJWK: string): Promise<string>;

  // Re-authentication methods
  // Authenticate user with biometric or PIN. If title/subtitle are null/empty, defaults to "Unlock Vault" context.
  // allowedMethods: Optional array of allowed methods ('biometric', 'pin', 'password'). If null/empty, all enabled methods are allowed.
  // buttonText: Optional custom text for the unlock/confirm button. If null/empty, defaults to "Unlock".
  // recentUnlockGraceSeconds: If > 0, skip the prompt when a successful biometric or PIN unlock happened within this many seconds ago. Pass 0 to always prompt.
  authenticateUser(title: string | null, subtitle: string | null, allowedMethods: string[] | null, buttonText: string | null, recentUnlockGraceSeconds: number): Promise<boolean>;

  // QR code scanner
  // Scan a QR code and return the scanned data. Returns null if cancelled or failed.
  // If prefixes is provided, only QR codes starting with one of these prefixes will be accepted.
  // Scanner will keep scanning until a matching code is found or user cancels.
  // statusText is the message to display on the scanner screen (defaults to "Scan QR code" if null/empty).
  scanQRCode(prefixes: string[] | null, statusText: string | null): Promise<string | null>;

  // Password generator (uses the native Rust core, shared with the other AliasVault clients)
  // Generate a password or passphrase from a JSON-serialized PasswordSettings object.
  generatePassword(settingsJson: string): Promise<string>;
  // List the bundled Diceware wordlist language codes (first is the default, English).
  getDicewareLanguages(): Promise<string[]>;

  // SRP (Secure Remote Password) operations
  // These methods use the native Rust SRP implementation for secure authentication.
  // All hex values are uppercase strings.

  // Generate a 32-byte random salt as uppercase hex string
  srpGenerateSalt(): Promise<string>;

  // Derive SRP private key: x = H(salt | H(identity | ":" | passwordHash))
  // passwordHash should be uppercase hex string (from Argon2id derivation)
  srpDerivePrivateKey(salt: string, identity: string, passwordHash: string): Promise<string>;

  // Derive SRP verifier: v = g^x mod N (for registration)
  srpDeriveVerifier(privateKey: string): Promise<string>;

  // Generate client ephemeral key pair (public A and secret a)
  srpGenerateEphemeral(): Promise<{public: string; secret: string}>;

  // Derive client session from server response
  // Returns proof (M1) and shared key (K) as uppercase hex strings
  srpDeriveSession(clientSecret: string, serverPublic: string, salt: string, identity: string, privateKey: string): Promise<{proof: string; key: string}>;
}

export default TurboModuleRegistry.getEnforcing<Spec>('NativeVaultManager');
