import { base64FromBytes, bytesFromBase64, type SecretStore } from '@chat-app/shared/auth';

import { isTauriRuntime } from './globalShortcut';
import { makeSecureFileStore, migrateLocalStorageToVault } from './secureFileStore';

// Two-tier SecretStore:
//   - Tauri runtime: encrypted single-file vault in `appLocalDataDir`
//     (`secureFileStore` — XSalsa20-Poly1305 + Argon2id KDF). Survives app
//     reinstalls when the OS preserves the data dir.
//   - Web / pre-auth: plain localStorage (legacy fallback).
//
// Callers import `devLocalSecretStore` and call `setSecretStoreUser(userId)`
// once the session is known. The singleton object's identity is stable so
// existing imports keep working.

const PREFIX = 'chatapp.secret:';

const localStore: SecretStore = {
  async getSecret(key: string): Promise<Uint8Array | null> {
    const raw = window.localStorage.getItem(PREFIX + key);
    if (!raw) return null;
    return bytesFromBase64(raw);
  },
  async setSecret(key: string, value: Uint8Array): Promise<void> {
    const encoded = await base64FromBytes(value);
    window.localStorage.setItem(PREFIX + key, encoded);
  },
  async removeSecret(key: string): Promise<void> {
    window.localStorage.removeItem(PREFIX + key);
  },
};

let activeBackend: SecretStore = localStore;
let activeUserId: string | null = null;

export async function setSecretStoreUser(userId: string | null): Promise<void> {
  if (userId === activeUserId) return;
  activeUserId = userId;

  if (userId && isTauriRuntime()) {
    const fileStore = makeSecureFileStore(userId);
    try {
      // Probe write/read to confirm the vault is usable on this machine.
      // If anything throws (perm denied, disk full, KDF error), fall back to
      // localStorage so the rest of the app keeps working.
      await fileStore.getSecret('__probe');
      activeBackend = fileStore;
      try {
        await migrateLocalStorageToVault(userId, PREFIX);
      } catch (err: unknown) {
        console.warn('vault migration failed', err);
      }
    } catch (err: unknown) {
      console.warn('secure file vault init failed — falling back to localStorage', err);
      activeBackend = localStore;
    }
  } else {
    activeBackend = localStore;
  }
}

export const devLocalSecretStore: SecretStore = {
  async getSecret(key) {
    return activeBackend.getSecret(key);
  },
  async setSecret(key, value) {
    return activeBackend.setSecret(key, value);
  },
  async removeSecret(key) {
    return activeBackend.removeSecret(key);
  },
};

export function isEncryptedVaultActive(): boolean {
  return activeBackend !== localStore;
}
