import fs from "node:fs";
import crypto from "node:crypto";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { env } from "../config/env.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const apiRoot = path.resolve(__dirname, "../..");
const workspaceRoot = path.resolve(apiRoot, "../..");

export const storageRoot = path.resolve(workspaceRoot, env.STORAGE_ROOT);
export const receiptsStorageDir = path.join(storageRoot, "receipts");
export const productMediaStorageDir = path.join(storageRoot, "product-media");
export const incidentAttachmentsStorageDir = path.join(storageRoot, "incident-attachments");

export function ensureReceiptStorage(): void {
  fs.mkdirSync(receiptsStorageDir, { recursive: true });
  fs.mkdirSync(productMediaStorageDir, { recursive: true });
  fs.mkdirSync(incidentAttachmentsStorageDir, { recursive: true });
}

function getEncryptionKey(): Buffer | null {
  if (!env.FILE_ENCRYPTION_ENABLED || !env.FILE_ENCRYPTION_KEY_BASE64) return null;
  const key = Buffer.from(env.FILE_ENCRYPTION_KEY_BASE64, "base64");
  return key.length === 32 ? key : null;
}

export function isFileEncryptionEnabled(): boolean {
  return Boolean(getEncryptionKey());
}

export function encryptBuffer(buffer: Buffer): Buffer {
  const key = getEncryptionKey();
  if (!key) return buffer;
  const iv = crypto.randomBytes(12);
  const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
  const encrypted = Buffer.concat([cipher.update(buffer), cipher.final()]);
  const tag = cipher.getAuthTag();
  return Buffer.concat([Buffer.from("TTENC1"), iv, tag, encrypted]);
}

export function decryptBuffer(buffer: Buffer): Buffer {
  const key = getEncryptionKey();
  if (!key) return buffer;
  const magic = buffer.subarray(0, 6).toString("utf8");
  if (magic !== "TTENC1") return buffer;
  const iv = buffer.subarray(6, 18);
  const tag = buffer.subarray(18, 34);
  const encrypted = buffer.subarray(34);
  const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
  decipher.setAuthTag(tag);
  return Buffer.concat([decipher.update(encrypted), decipher.final()]);
}

export async function writeEncryptedFile(filePath: string, data: Buffer): Promise<void> {
  await fs.promises.writeFile(filePath, encryptBuffer(data));
}

export async function readEncryptedFile(filePath: string): Promise<Buffer> {
  const data = await fs.promises.readFile(filePath);
  return decryptBuffer(data);
}
