import * as Minio from 'minio';
import * as https from 'node:https';
import type { Readable } from 'node:stream';

interface UploadableFile {
  filename: string;
  file: Readable | Buffer;
}

let minioClient: Minio.Client | null = null;

function getClient(): Minio.Client | null {
  if (minioClient) return minioClient;

  if (!process.env.MINIO_ENDPOINT || !process.env.MINIO_ACCESS_KEY) {
    return null;
  }

  const useSSL = process.env.MINIO_USE_SSL === 'true';
  const allowSelfSigned = process.env.MINIO_ALLOW_SELF_SIGNED === 'true';

  const clientOpts: Minio.ClientOptions = {
    endPoint: process.env.MINIO_ENDPOINT.replace(/^https?:\/\//, ''),
    port: parseInt(process.env.MINIO_PORT ?? '9000', 10),
    useSSL,
    accessKey: process.env.MINIO_ACCESS_KEY,
    secretKey: process.env.MINIO_SECRET_KEY ?? '',
    pathStyle: true,
  };

  // Ne désactiver la vérification TLS que si explicitement demandé.
  // `transport` n'expose pas `agent` dans les types récents de minio ; on
  // passe par un cast ciblé car le runtime minio accepte toujours cette option.
  if (useSSL && allowSelfSigned) {
    (clientOpts as unknown as { transport: unknown }).transport = {
      agent: new https.Agent({ rejectUnauthorized: false }),
    };
  }

  minioClient = new Minio.Client(clientOpts);
  return minioClient;
}

function bucket(): string {
  const b = process.env.MINIO_BUCKET;
  if (!b) throw new Error('MINIO_BUCKET non défini');
  return b;
}

export async function uploadFile(file: UploadableFile, folderPath: string): Promise<string> {
  const client = getClient();
  if (!client) throw new Error('MinIO non configuré');

  const fileName = `${Date.now()}-${file.filename}`;
  const filePath = `${folderPath}/${fileName}`;
  await client.putObject(bucket(), filePath, file.file);
  return filePath;
}

export async function deleteFile(filePath: string): Promise<void> {
  const client = getClient();
  if (!client) return;
  await client.removeObject(bucket(), filePath);
}

export async function getFile(filePath: string): Promise<Readable> {
  const client = getClient();
  if (!client) throw new Error('MinIO non configuré');
  return client.getObject(bucket(), filePath);
}

export async function listFiles(folderPath: string) {
  const client = getClient();
  if (!client) throw new Error('MinIO non configuré');
  return client.listObjects(bucket(), folderPath);
}

export async function getFileUrl(filePath: string): Promise<string> {
  const client = getClient();
  if (!client) throw new Error('MinIO non configuré');
  return client.presignedUrl('GET', bucket(), filePath);
}
