import { assert, assertEquals } from '@std/assert';

import type { IRegistry } from '../ts/types.ts';
import { credentialEncryption } from '../ts/classes/encryption.ts';
import { OneboxRegistriesManager } from '../ts/classes/registries.ts';

class FakeRegistryDatabase {
  private registries = new Map<string, IRegistry>();

  getRegistryByURL(url: string): IRegistry | null {
    return this.registries.get(url) ?? null;
  }

  async createRegistry(registry: Omit<IRegistry, 'id'>): Promise<IRegistry> {
    const savedRegistry: IRegistry = {
      id: this.registries.size + 1,
      ...registry,
    };
    this.registries.set(savedRegistry.url, savedRegistry);
    return savedRegistry;
  }

  deleteRegistry(url: string): void {
    this.registries.delete(url);
  }

  getAllRegistries(): IRegistry[] {
    return Array.from(this.registries.values());
  }
}

Deno.test('credential encryption lazily initializes and roundtrips payloads', async () => {
  const encrypted = await credentialEncryption.encrypt({ password: 'super-secret' });
  const decrypted = await credentialEncryption.decrypt<{ password: string }>(encrypted);

  assert(encrypted.length > 0);
  assertEquals(decrypted.password, 'super-secret');
});

Deno.test('registry passwords use encrypted storage with legacy decode fallback', async () => {
  const fakeDatabase = new FakeRegistryDatabase();
  const registriesManager = new OneboxRegistriesManager({ database: fakeDatabase } as any);

  (registriesManager as any).loginToRegistry = async () => {};

  const registry = await registriesManager.addRegistry(
    'registry.example.com',
    'ci-user',
    'correct horse battery staple',
  );

  assert(registry.passwordEncrypted.startsWith('enc:v1:'));
  assertEquals(
    await (registriesManager as any).decryptPassword(registry.passwordEncrypted),
    'correct horse battery staple',
  );
  assertEquals(
    await (registriesManager as any).decryptPassword(btoa('legacy-password')),
    'legacy-password',
  );
});
