import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
import path from 'node:path';

export const CERTIFICATE_MAX_FILE_SIZE = 10 * 1024 * 1024;
export const CERTIFICATE_ACCEPTED_TYPES = [
  'application/pdf',
  'image/jpeg',
  'image/jpg',
  'image/png'
] as const;

const PUBLIC_UPLOAD_ROOT = path.join(process.cwd(), 'public', 'uploads', 'certificates');

function sanitizeSegment(value: string) {
  return value.replace(/[^a-zA-Z0-9._-]/g, '-');
}

function ensureWithinUploadRoot(targetPath: string) {
  const normalizedRoot = path.resolve(PUBLIC_UPLOAD_ROOT);
  const normalizedTarget = path.resolve(targetPath);

  if (!normalizedTarget.startsWith(normalizedRoot)) {
    throw new Error('Invalid certificate storage path');
  }
}

export async function saveCertificateFile({
  file,
  organizationId,
  trainingRecordId
}: {
  file: File;
  organizationId: string;
  trainingRecordId: number;
}) {
  if (!CERTIFICATE_ACCEPTED_TYPES.includes(file.type as (typeof CERTIFICATE_ACCEPTED_TYPES)[number])) {
    throw new Error('Unsupported certificate file type');
  }

  if (file.size > CERTIFICATE_MAX_FILE_SIZE) {
    throw new Error('Certificate file exceeds the maximum size of 10MB');
  }

  const extension = path.extname(file.name) || (file.type === 'application/pdf' ? '.pdf' : '.png');
  const baseName = sanitizeSegment(path.basename(file.name, extension)) || 'certificate';
  const uniqueName = `${Date.now()}-${crypto.randomUUID()}-${baseName}${extension}`;
  const storageKey = path.join(
    sanitizeSegment(organizationId),
    String(trainingRecordId),
    uniqueName
  );
  const absoluteDirectory = path.join(
    PUBLIC_UPLOAD_ROOT,
    sanitizeSegment(organizationId),
    String(trainingRecordId)
  );
  const absolutePath = path.join(absoluteDirectory, uniqueName);

  ensureWithinUploadRoot(absolutePath);
  await mkdir(absoluteDirectory, { recursive: true });
  const bytes = Buffer.from(await file.arrayBuffer());
  await writeFile(absolutePath, bytes);

  return {
    storageKey: storageKey.replaceAll('\\', '/'),
    fileUrl: `/uploads/certificates/${storageKey.replaceAll('\\', '/')}`,
    fileName: file.name,
    fileType: file.type,
    fileSize: file.size
  };
}

export async function deleteStoredCertificate(storageKey: string) {
  const absolutePath = path.join(PUBLIC_UPLOAD_ROOT, storageKey);
  ensureWithinUploadRoot(absolutePath);

  try {
    await unlink(absolutePath);
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
      throw error;
    }
  }
}

export async function readStoredCertificate(storageKey: string) {
  const absolutePath = path.join(PUBLIC_UPLOAD_ROOT, storageKey);
  ensureWithinUploadRoot(absolutePath);

  return readFile(absolutePath);
}
