/**
 * File Storage Utility for Brand Assets
 *
 * Saves brand asset images to the filesystem (uploads/brand-assets/)
 * instead of storing base64 data in MongoDB.
 */

import fs from 'fs';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';

const BRAND_ASSETS_DIR = path.resolve(process.cwd(), 'uploads', 'brand-assets');

// Ensure brand-assets directory exists
if (!fs.existsSync(BRAND_ASSETS_DIR)) {
  fs.mkdirSync(BRAND_ASSETS_DIR, { recursive: true });
}

/** MIME type → file extension mapping */
const MIME_TO_EXT: Record<string, string> = {
  'image/png': 'png',
  'image/jpeg': 'jpg',
  'image/webp': 'webp',
  'image/gif': 'gif',
  'image/svg+xml': 'svg',
  'image/x-icon': 'ico',
  'image/vnd.microsoft.icon': 'ico',
  'application/pdf': 'pdf',
};

/**
 * Get file extension from a MIME type.
 * Falls back to `fallbackExt` (defaults to 'png') if the MIME type is unknown.
 */
export function getExtensionFromMime(mimeType: string, fallbackExt = 'png'): string {
  return MIME_TO_EXT[mimeType] || fallbackExt;
}

/**
 * Parse a base64 data-URI string into a Buffer and MIME type.
 * Accepts both "data:image/png;base64,..." format and raw base64.
 *
 * @param base64Data - The base64 string, optionally prefixed with data-URI header
 * @param fallbackMime - MIME type to use if not present in the data-URI header
 * @returns { buffer, mimeType } where buffer is the decoded image bytes
 */
export function base64ToBuffer(
  base64Data: string,
  fallbackMime = 'image/png'
): { buffer: Buffer; mimeType: string } {
  // Check for data-URI prefix: "data:image/png;base64,ABC123..."
  const dataUriMatch = base64Data.match(/^data:([^;]+);base64,(.+)$/s);

  if (dataUriMatch) {
    const mimeType = dataUriMatch[1];
    const rawBase64 = dataUriMatch[2];
    return {
      buffer: Buffer.from(rawBase64, 'base64'),
      mimeType,
    };
  }

  // Raw base64 without data-URI prefix
  return {
    buffer: Buffer.from(base64Data, 'base64'),
    mimeType: fallbackMime,
  };
}

/**
 * Save a Buffer to the uploads/brand-assets/ directory with a UUID filename.
 *
 * @param buffer - The file data to save
 * @param originalFilename - Original filename (used to extract extension as fallback)
 * @param mimeType - MIME type to determine file extension
 * @returns { url, filePath, fileSize } where url is the relative web path
 */
export async function saveBrandAssetFile(
  buffer: Buffer,
  originalFilename: string,
  mimeType: string
): Promise<{ url: string; filePath: string; fileSize: number }> {
  // Ensure directory exists
  if (!fs.existsSync(BRAND_ASSETS_DIR)) {
    fs.mkdirSync(BRAND_ASSETS_DIR, { recursive: true });
  }

  const ext = getExtensionFromMime(mimeType) || path.extname(originalFilename).slice(1) || 'png';
  const filename = `${uuidv4()}.${ext}`;
  const filePath = path.join(BRAND_ASSETS_DIR, filename);

  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, buffer, (err) => {
      if (err) {
        reject(err);
        return;
      }
      resolve({
        url: `/uploads/brand-assets/${filename}`,
        filePath,
        fileSize: buffer.length,
      });
    });
  });
}

/**
 * Delete a brand asset file from disk by its URL path.
 * No-op if the file doesn't exist or the URL is not a local filesystem path.
 *
 * @param url - The relative URL path (e.g., /uploads/brand-assets/abc123.png)
 */
export async function deleteBrandAssetFile(url: string): Promise<void> {
  // Only delete files that are stored locally in our brand-assets directory
  if (!url || !url.startsWith('/uploads/brand-assets/')) {
    return;
  }

  const filename = url.replace('/uploads/brand-assets/', '');
  const filePath = path.join(BRAND_ASSETS_DIR, filename);

  return new Promise((resolve) => {
    fs.unlink(filePath, (err) => {
      if (err && err.code !== 'ENOENT') {
        console.error(`[FileStorage] Failed to delete ${filePath}:`, err.message);
      }
      resolve();
    });
  });
}

// ============================================
// HR ASSET FILE STORAGE
// ============================================

const HR_ASSETS_DIR = path.resolve(process.cwd(), 'uploads', 'hr-assets');

// Ensure hr-assets directory exists
if (!fs.existsSync(HR_ASSETS_DIR)) {
  fs.mkdirSync(HR_ASSETS_DIR, { recursive: true });
}

/**
 * Save a Buffer to the uploads/hr-assets/ directory with a UUID filename.
 *
 * @param buffer - The file data to save
 * @param originalFilename - Original filename (used to extract extension as fallback)
 * @param mimeType - MIME type to determine file extension
 * @returns { url, filePath, fileSize } where url is the relative web path
 */
export async function saveHrAssetFile(
  buffer: Buffer,
  originalFilename: string,
  mimeType: string
): Promise<{ url: string; filePath: string; fileSize: number }> {
  // Ensure directory exists
  if (!fs.existsSync(HR_ASSETS_DIR)) {
    fs.mkdirSync(HR_ASSETS_DIR, { recursive: true });
  }

  const ext = getExtensionFromMime(mimeType) || path.extname(originalFilename).slice(1) || 'png';
  const filename = `${uuidv4()}.${ext}`;
  const filePath = path.join(HR_ASSETS_DIR, filename);

  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, buffer, (err) => {
      if (err) {
        reject(err);
        return;
      }
      resolve({
        url: `/uploads/hr-assets/${filename}`,
        filePath,
        fileSize: buffer.length,
      });
    });
  });
}

/**
 * Delete an HR asset file from disk by its URL path.
 * No-op if the file doesn't exist or the URL is not a local filesystem path.
 *
 * @param url - The relative URL path (e.g., /uploads/hr-assets/abc123.png)
 */
export async function deleteHrAssetFile(url: string): Promise<void> {
  // Only delete files that are stored locally in our hr-assets directory
  if (!url || !url.startsWith('/uploads/hr-assets/')) {
    return;
  }

  const filename = url.replace('/uploads/hr-assets/', '');
  const filePath = path.join(HR_ASSETS_DIR, filename);

  return new Promise((resolve) => {
    fs.unlink(filePath, (err) => {
      if (err && err.code !== 'ENOENT') {
        console.error(`[FileStorage] Failed to delete HR asset ${filePath}:`, err.message);
      }
      resolve();
    });
  });
}

// ============================================
// STATIONERY FILE STORAGE
// ============================================

const STATIONERY_DIR = path.resolve(process.cwd(), 'uploads', 'stationery');

// Ensure stationery directory exists
if (!fs.existsSync(STATIONERY_DIR)) {
  fs.mkdirSync(STATIONERY_DIR, { recursive: true });
}

/**
 * Save a Buffer to the uploads/stationery/ directory with a UUID filename.
 *
 * @param buffer - The file data to save
 * @param originalFilename - Original filename (used to extract extension as fallback)
 * @param mimeType - MIME type to determine file extension
 * @returns { url, filePath, fileSize } where url is the relative web path
 */
export async function saveStationeryFile(
  buffer: Buffer,
  originalFilename: string,
  mimeType: string
): Promise<{ url: string; filePath: string; fileSize: number }> {
  // Ensure directory exists
  if (!fs.existsSync(STATIONERY_DIR)) {
    fs.mkdirSync(STATIONERY_DIR, { recursive: true });
  }

  const ext = getExtensionFromMime(mimeType) || path.extname(originalFilename).slice(1) || 'png';
  const filename = `${uuidv4()}.${ext}`;
  const filePath = path.join(STATIONERY_DIR, filename);

  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, buffer, (err) => {
      if (err) {
        reject(err);
        return;
      }
      resolve({
        url: `/uploads/stationery/${filename}`,
        filePath,
        fileSize: buffer.length,
      });
    });
  });
}

/**
 * Delete a stationery file from disk by its URL path.
 * No-op if the file doesn't exist or the URL is not a local filesystem path.
 *
 * @param url - The relative URL path (e.g., /uploads/stationery/abc123.png)
 */
export async function deleteStationeryFile(url: string): Promise<void> {
  // Only delete files that are stored locally in our stationery directory
  if (!url || !url.startsWith('/uploads/stationery/')) {
    return;
  }

  const filename = url.replace('/uploads/stationery/', '');
  const filePath = path.join(STATIONERY_DIR, filename);

  return new Promise((resolve) => {
    fs.unlink(filePath, (err) => {
      if (err && err.code !== 'ENOENT') {
        console.error(`[FileStorage] Failed to delete stationery file ${filePath}:`, err.message);
      }
      resolve();
    });
  });
}