import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
import { createClient } from 'redis';

const redis = createClient({ url: process.env.REDIS_URL });
redis.connect().catch((err) => console.error('[credential-store] Redis connect error:', err));

const ENCRYPTION_KEY = Buffer.from(process.env.CREDENTIAL_ENCRYPTION_KEY ?? '0'.repeat(64), 'hex');
// CREDENTIAL_ENCRYPTION_KEY must be a 64-char hex string (32 bytes)
// Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

function encrypt(plaintext: string): string {
  const iv = randomBytes(12);
  const cipher = createCipheriv('aes-256-gcm', ENCRYPTION_KEY, iv);
  const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
  const tag = cipher.getAuthTag();
  return `${iv.toString('hex')}:${tag.toString('hex')}:${encrypted.toString('hex')}`;
}

function decrypt(ciphertext: string): string {
  const [ivHex, tagHex, encHex] = ciphertext.split(':');
  const iv = Buffer.from(ivHex, 'hex');
  const tag = Buffer.from(tagHex, 'hex');
  const encrypted = Buffer.from(encHex, 'hex');
  const decipher = createDecipheriv('aes-256-gcm', ENCRYPTION_KEY, iv);
  decipher.setAuthTag(tag);
  return decipher.update(encrypted) + decipher.final('utf8');
}

export type Platform = 'email' | 'whatsapp' | 'linkedin' | 'telegram' | 'discord' | 'instagram' | 'twitter' | 'obsidian';

export interface EmailCredentials {
  host: string;
  port: number;
  user: string;
  password: string;
  smtpHost?: string;
  smtpPort?: number;
}

export interface OAuthCredentials {
  accessToken: string;
  refreshToken?: string;
  expiresAt?: number;
  scope?: string;
}

export interface WhatsAppCredentials {
  phoneNumberId: string;
  accessToken: string;
  businessAccountId: string;
}

export type PlatformCredentials = EmailCredentials | OAuthCredentials | WhatsAppCredentials | Record<string, string>;

export async function storeCredential(
  customerId: string,
  platform: Platform,
  credentials: PlatformCredentials
): Promise<void> {
  const key = `creds:${customerId}:${platform}`;
  const encrypted = encrypt(JSON.stringify(credentials));
  // Credentials don't expire — they persist until explicitly revoked
  await redis.set(key, encrypted);
}

export async function getCredential<T extends PlatformCredentials>(
  customerId: string,
  platform: Platform
): Promise<T | null> {
  const key = `creds:${customerId}:${platform}`;
  const encrypted = await redis.get(key);
  if (!encrypted) return null;
  return JSON.parse(decrypt(encrypted)) as T;
}

export async function revokeCredential(customerId: string, platform: Platform): Promise<void> {
  await redis.del(`creds:${customerId}:${platform}`);
}

export async function revokeAllCredentials(customerId: string): Promise<void> {
  const pattern = `creds:${customerId}:*`;
  const keys = await redis.keys(pattern);
  if (keys.length > 0) await redis.del(keys);
}
