/**
 * Blog Management Validators
 * Validation rules for blog post creation and updates
 */

import validator from 'validator';
import type { CreateBlogPostInput, UpdateBlogPostInput, BlogStatus } from '@/lib/types/blog-management.types';

/**
 * Validation error class
 */
export class BlogValidationError extends Error {
  constructor(
    message: string,
    public field?: string
  ) {
    super(message);
    this.name = 'BlogValidationError';
  }
}

/**
 * Validate slug format
 * Must be URL-friendly: lowercase, hyphens, no special chars
 */
function validateSlug(slug: string): void {
  if (!slug || typeof slug !== 'string') {
    throw new BlogValidationError('Slug is required', 'slug');
  }

  if (slug.length < 3 || slug.length > 200) {
    throw new BlogValidationError('Slug must be between 3 and 200 characters', 'slug');
  }

  // Must be URL-friendly
  const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
  if (!slugRegex.test(slug)) {
    throw new BlogValidationError(
      'Slug must contain only lowercase letters, numbers, and hyphens',
      'slug'
    );
  }

  // Reserved slugs
  const reserved = ['new', 'create', 'edit', 'delete', 'admin', 'api'];
  if (reserved.includes(slug)) {
    throw new BlogValidationError(`Slug '${slug}' is reserved`, 'slug');
  }
}

/**
 * Validate language
 */
function validateLanguage(lang: string): void {
  if (!lang || !['ar', 'en'].includes(lang)) {
    throw new BlogValidationError('Language must be either "ar" or "en"', 'lang');
  }
}

/**
 * Validate title
 */
function validateTitle(title: string): void {
  if (!title || typeof title !== 'string') {
    throw new BlogValidationError('Title is required', 'title');
  }

  const trimmed = title.trim();
  if (trimmed.length < 5 || trimmed.length > 200) {
    throw new BlogValidationError('Title must be between 5 and 200 characters', 'title');
  }
}

/**
 * Validate excerpt
 */
function validateExcerpt(excerpt: string): void {
  if (!excerpt || typeof excerpt !== 'string') {
    throw new BlogValidationError('Excerpt is required', 'excerpt');
  }

  const trimmed = excerpt.trim();
  if (trimmed.length < 20 || trimmed.length > 500) {
    throw new BlogValidationError('Excerpt must be between 20 and 500 characters', 'excerpt');
  }
}

/**
 * Validate content
 */
function validateContent(content: string): void {
  if (!content || typeof content !== 'string') {
    throw new BlogValidationError('Content is required', 'content');
  }

  const trimmed = content.trim();
  if (trimmed.length < 100) {
    throw new BlogValidationError('Content must be at least 100 characters', 'content');
  }

  if (trimmed.length > 100000) {
    throw new BlogValidationError('Content must be less than 100,000 characters', 'content');
  }
}

/**
 * Validate author
 */
function validateAuthor(author: string): void {
  if (!author || typeof author !== 'string') {
    throw new BlogValidationError('Author is required', 'author');
  }

  const trimmed = author.trim();
  if (trimmed.length < 2 || trimmed.length > 100) {
    throw new BlogValidationError('Author must be between 2 and 100 characters', 'author');
  }
}

/**
 * Validate tags array
 */
function validateTags(tags: string[] | undefined): void {
  if (!tags) return; // Tags are optional

  if (!Array.isArray(tags)) {
    throw new BlogValidationError('Tags must be an array', 'tags');
  }

  if (tags.length > 10) {
    throw new BlogValidationError('Maximum 10 tags allowed', 'tags');
  }

  tags.forEach((tag, index) => {
    if (typeof tag !== 'string' || tag.trim().length === 0) {
      throw new BlogValidationError(`Tag at index ${index} is invalid`, 'tags');
    }

    if (tag.length > 50) {
      throw new BlogValidationError(`Tag '${tag}' exceeds 50 characters`, 'tags');
    }
  });
}

/**
 * Validate status
 */
function validateStatus(status: BlogStatus | undefined): void {
  if (!status) return; // Status is optional (defaults to DRAFT)

  const validStatuses: BlogStatus[] = ['DRAFT', 'PUBLISHED', 'ARCHIVED'];
  if (!validStatuses.includes(status)) {
    throw new BlogValidationError(
      `Status must be one of: ${validStatuses.join(', ')}`,
      'status'
    );
  }
}

/**
 * Validate date
 */
function validateDate(date: string | undefined): void {
  if (!date) return; // Date is optional

  if (!validator.isISO8601(date)) {
    throw new BlogValidationError('Date must be in ISO 8601 format (YYYY-MM-DD)', 'date');
  }
}

/**
 * Validate meta description
 */
function validateMetaDescription(metaDescription: string | undefined): void {
  if (!metaDescription) return;

  if (metaDescription.length > 160) {
    throw new BlogValidationError('Meta description must be 160 characters or less', 'meta_description');
  }
}

/**
 * Validate meta keywords
 */
function validateMetaKeywords(metaKeywords: string[] | undefined): void {
  if (!metaKeywords) return;

  if (!Array.isArray(metaKeywords)) {
    throw new BlogValidationError('Meta keywords must be an array', 'meta_keywords');
  }

  if (metaKeywords.length > 15) {
    throw new BlogValidationError('Maximum 15 meta keywords allowed', 'meta_keywords');
  }
}

/**
 * Validate create blog post input
 */
export function validateCreateBlogPost(input: CreateBlogPostInput): void {
  validateSlug(input.slug);
  validateLanguage(input.lang);
  validateTitle(input.title);
  validateExcerpt(input.excerpt);
  validateContent(input.content);
  validateAuthor(input.author);
  validateTags(input.tags);
  validateStatus(input.status);
  validateDate(input.date);
  validateMetaDescription(input.meta_description);
  validateMetaKeywords(input.meta_keywords);

  // Validate featured order if featured is true
  if (input.featured && input.featured_order !== undefined) {
    if (!Number.isInteger(input.featured_order) || input.featured_order < 0) {
      throw new BlogValidationError('Featured order must be a non-negative integer', 'featured_order');
    }
  }
}

/**
 * Validate update blog post input
 */
export function validateUpdateBlogPost(input: UpdateBlogPostInput): void {
  // At least one field must be provided
  const hasUpdates = Object.keys(input).length > 0;
  if (!hasUpdates) {
    throw new BlogValidationError('At least one field must be provided for update');
  }

  // Validate each field if provided
  if (input.slug !== undefined) validateSlug(input.slug);
  if (input.title !== undefined) validateTitle(input.title);
  if (input.excerpt !== undefined) validateExcerpt(input.excerpt);
  if (input.content !== undefined) validateContent(input.content);
  if (input.author !== undefined) validateAuthor(input.author);
  if (input.tags !== undefined) validateTags(input.tags);
  if (input.status !== undefined) validateStatus(input.status);
  if (input.date !== undefined) validateDate(input.date);
  if (input.meta_description !== undefined) validateMetaDescription(input.meta_description);
  if (input.meta_keywords !== undefined) validateMetaKeywords(input.meta_keywords);
}

/**
 * Calculate reading time from content
 * Average reading speed: 200 words per minute
 */
export function calculateReadingTime(content: string): number {
  const wordsPerMinute = 200;
  const wordCount = content.trim().split(/\s+/).length;
  const minutes = Math.ceil(wordCount / wordsPerMinute);
  return Math.max(1, minutes); // Minimum 1 minute
}

/**
 * Generate slug from title
 * Converts title to URL-friendly slug
 */
export function generateSlugFromTitle(title: string, lang: 'ar' | 'en'): string {
  // For Arabic, check original title before stripping characters
  if (lang === 'ar' && /[\u0600-\u06FF]/.test(title)) {
    return `blog-${Date.now()}`;
  }

  const slug = title
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, '') // Remove special chars
    .replace(/\s+/g, '-') // Replace spaces with hyphens
    .replace(/-+/g, '-') // Replace multiple hyphens with single
    .replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens

  return slug;
}
