// {{ display_name }} MCP server — generated by mcpify. Do not hand-edit.

import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';

import { logger } from './logger.js';

const SERVICE_NAME = '{{ project_name }}';
const CONFIG_DIR = join(homedir(), '.{{ project_name }}');
const FALLBACK_FILE = join(CONFIG_DIR, 'credentials.enc');

let keytarModule: typeof import('keytar') | undefined;
try {
  keytarModule = await import('keytar');
} catch {
  logger.warn('OS keychain unavailable; falling back to encrypted file storage');
}

function encryptionKey(): Buffer {
  // Derived from a machine/user-specific value so the encrypted fallback
  // file isn't portable to another machine by design, mirroring the
  // OS keychain's own implicit scoping.
  return scryptSync(homedir(), SERVICE_NAME, 32);
}

function readStore(): Record<string, string> {
  if (!existsSync(FALLBACK_FILE)) return {};
  return JSON.parse(readFileSync(FALLBACK_FILE, 'utf8'));
}

function writeStore(store: Record<string, string>): void {
  mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
  writeFileSync(FALLBACK_FILE, JSON.stringify(store), { mode: 0o600 });
}

function saveToFile(account: string, value: string): void {
  const store = readStore();
  const iv = randomBytes(16);
  const cipher = createCipheriv('aes-256-cbc', encryptionKey(), iv);
  const encrypted = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]);
  store[account] = `${iv.toString('hex')}:${encrypted.toString('hex')}`;
  writeStore(store);
}

function loadFromFile(account: string): string | undefined {
  const raw = readStore()[account];
  if (!raw) return undefined;
  const [ivHex, dataHex] = raw.split(':');
  const decipher = createDecipheriv('aes-256-cbc', encryptionKey(), Buffer.from(ivHex, 'hex'));
  return Buffer.concat([decipher.update(Buffer.from(dataHex, 'hex')), decipher.final()]).toString('utf8');
}

/**
 * Persists a credential to the OS-native keychain when available (macOS
 * Keychain, Windows Credential Manager, Linux Secret Service via `keytar`),
 * falling back to an encrypted local file with in-memory caching handled by
 * the caller — REQ-2.3.5.
 */
export async function saveCredential(account: string, value: string): Promise<void> {
  if (keytarModule) {
    await keytarModule.setPassword(SERVICE_NAME, account, value);
    return;
  }
  saveToFile(account, value);
}

export async function loadCredential(account: string): Promise<string | undefined> {
  if (keytarModule) {
    return (await keytarModule.getPassword(SERVICE_NAME, account)) ?? undefined;
  }
  return loadFromFile(account);
}

export async function deleteCredential(account: string): Promise<void> {
  if (keytarModule) {
    await keytarModule.deletePassword(SERVICE_NAME, account);
    return;
  }
  if (!existsSync(FALLBACK_FILE)) return;
  const store = readStore();
  delete store[account];
  writeStore(store);
}
