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

import { isTauriRuntime } from './globalShortcut';
import {
  makeStrongholdStore,
  migrateLocalStorageToStronghold,
} from './strongholdStore';

// Two-tier SecretStore:
//   - Electron runtime: safeStorage-backed store in `<userData>`
//     (`strongholdStore`). DPAPI on Windows / Keychain on macOS /
//     libsecret on Linux seals the per-user blob. 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 store = makeStrongholdStore(userId);
    try {
      // Probe read to confirm the store is usable on this machine. If
      // anything throws, fall back to localStorage so the rest of the
      // app keeps working.
      await store.getSecret('__probe');
      activeBackend = store;
      try {
        await migrateLocalStorageToStronghold(userId, PREFIX);
      } catch (err: unknown) {
        console.warn('vault migration failed', err);
      }
    } catch (err: unknown) {
      console.warn('secure store 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;
}
