const AssetsDBApi = require('../db/api/assets');
const { createEntityService } = require('../factories/service.factory');
const ValidationError = require('./notifications/errors/validation');

/**
 * Valid MIME type patterns for each asset type
 */
const VALID_MIME_PATTERNS = {
  image: {
    prefixes: ['image/'],
    description: 'image (jpeg, png, gif, webp, svg, etc.)',
  },
  video: {
    prefixes: ['video/'],
    description: 'video (mp4, webm, mov, etc.)',
  },
  audio: {
    prefixes: ['audio/'],
    description: 'audio (mp3, wav, ogg, etc.)',
  },
};

/**
 * Validate that mime_type matches asset_type
 * @param {string} assetType - Expected asset type (image, video, audio)
 * @param {string} mimeType - Actual MIME type of the file
 * @returns {{ valid: boolean, error?: string }}
 */
function validateAssetMimeType(assetType, mimeType) {
  // If no asset_type specified, skip validation
  if (!assetType) {
    return { valid: true };
  }

  const patterns = VALID_MIME_PATTERNS[assetType];

  // If asset_type is not one we validate (e.g., 'file'), skip validation
  if (!patterns) {
    return { valid: true };
  }

  // If no mime_type provided, we can't validate but allow it
  // (browser may not always send mime type)
  if (!mimeType) {
    return { valid: true };
  }

  const normalizedMime = String(mimeType).toLowerCase().trim();

  // Check if mime_type matches any of the valid prefixes
  const isValid = patterns.prefixes.some((prefix) =>
    normalizedMime.startsWith(prefix),
  );

  if (!isValid) {
    return {
      valid: false,
      error: `Invalid file type for ${assetType}. Expected ${patterns.description}, got "${mimeType}"`,
    };
  }

  return { valid: true };
}

// Create base service from factory
const BaseService = createEntityService(AssetsDBApi, {
  entityName: 'assets',
});

/**
 * Assets Service with validation
 */
class AssetsService extends BaseService {
  /**
   * Create asset with MIME type validation
   */
  static async create(data, currentUser) {
    // Validate asset_type and mime_type match
    const assetType = data.asset_type;
    const mimeType = data.mime_type;

    const validation = validateAssetMimeType(assetType, mimeType);
    if (!validation.valid) {
      throw new ValidationError(validation.error);
    }

    // Call parent create
    return super.create(data, currentUser);
  }

  /**
   * Update asset with MIME type validation
   */
  static async update(data, id, currentUser) {
    // If updating asset_type or mime_type, validate they match
    if (data.asset_type || data.mime_type) {
      const assetType = data.asset_type;
      const mimeType = data.mime_type;

      // Only validate if both are provided in the update
      if (assetType && mimeType) {
        const validation = validateAssetMimeType(assetType, mimeType);
        if (!validation.valid) {
          throw new ValidationError(validation.error);
        }
      }
    }

    // Call parent update
    return super.update(data, id, currentUser);
  }
}

module.exports = AssetsService;
