/**
 * Alert Helper Utilities
 * Provides grouping, filtering, sorting, and categorization logic for alerts
 */

import { NotificationData } from '../hooks/useNotifications';

export type AlertSeverity = 'urgent' | 'high' | 'medium' | 'low';
export type AlertCategory = 'inventory' | 'production' | 'orders' | 'equipment' | 'quality' | 'suppliers' | 'other';
export type TimeGroup = 'today' | 'yesterday' | 'this_week' | 'older';

export interface AlertGroup {
  id: string;
  type: 'time' | 'category' | 'similarity';
  key: string;
  title: string;
  count: number;
  severity: AlertSeverity;
  alerts: NotificationData[];
  collapsed?: boolean;
}

export interface AlertFilters {
  severities: AlertSeverity[];
  categories: AlertCategory[];
  timeRange: TimeGroup | 'all';
  search: string;
  showSnoozed: boolean;
}

export interface SnoozedAlert {
  alertId: string;
  until: number; // timestamp
  reason?: string;
}

/**
 * Categorize alert based on title and message content
 */
export function categorizeAlert(alert: NotificationData): AlertCategory {
  const text = `${alert.title} ${alert.message}`.toLowerCase();

  if (text.includes('stock') || text.includes('inventario') || text.includes('caducad') || text.includes('expi')) {
    return 'inventory';
  }
  if (text.includes('producci') || text.includes('production') || text.includes('lote') || text.includes('batch')) {
    return 'production';
  }
  if (text.includes('pedido') || text.includes('order') || text.includes('entrega') || text.includes('delivery')) {
    return 'orders';
  }
  if (text.includes('equip') || text.includes('maquina') || text.includes('mantenimiento') || text.includes('maintenance')) {
    return 'equipment';
  }
  if (text.includes('calidad') || text.includes('quality') || text.includes('temperatura') || text.includes('temperature')) {
    return 'quality';
  }
  if (text.includes('proveedor') || text.includes('supplier') || text.includes('compra') || text.includes('purchase')) {
    return 'suppliers';
  }

  return 'other';
}

/**
 * Get category display name
 */
export function getCategoryName(category: AlertCategory, locale: string = 'es'): string {
  const names: Record<AlertCategory, Record<string, string>> = {
    inventory: { es: 'Inventario', en: 'Inventory' },
    production: { es: 'Producción', en: 'Production' },
    orders: { es: 'Pedidos', en: 'Orders' },
    equipment: { es: 'Maquinaria', en: 'Equipment' },
    quality: { es: 'Calidad', en: 'Quality' },
    suppliers: { es: 'Proveedores', en: 'Suppliers' },
    other: { es: 'Otros', en: 'Other' },
  };

  return names[category][locale] || names[category]['es'];
}

/**
 * Get category icon emoji
 */
export function getCategoryIcon(category: AlertCategory): string {
  const icons: Record<AlertCategory, string> = {
    inventory: '📦',
    production: '🏭',
    orders: '🚚',
    equipment: '⚙️',
    quality: '✅',
    suppliers: '🏢',
    other: '📋',
  };

  return icons[category];
}

/**
 * Determine time group for an alert
 */
export function getTimeGroup(timestamp: string): TimeGroup {
  const alertDate = new Date(timestamp);
  const now = new Date();

  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);
  const weekAgo = new Date(today);
  weekAgo.setDate(weekAgo.getDate() - 7);

  if (alertDate >= today) {
    return 'today';
  }
  if (alertDate >= yesterday) {
    return 'yesterday';
  }
  if (alertDate >= weekAgo) {
    return 'this_week';
  }
  return 'older';
}

/**
 * Get time group display name
 */
export function getTimeGroupName(group: TimeGroup, locale: string = 'es'): string {
  const names: Record<TimeGroup, Record<string, string>> = {
    today: { es: 'Hoy', en: 'Today' },
    yesterday: { es: 'Ayer', en: 'Yesterday' },
    this_week: { es: 'Esta semana', en: 'This week' },
    older: { es: 'Anteriores', en: 'Older' },
  };

  return names[group][locale] || names[group]['es'];
}

/**
 * Check if two alerts are similar enough to group together
 */
export function areAlertsSimilar(alert1: NotificationData, alert2: NotificationData): boolean {
  // Must be same category and severity
  if (categorizeAlert(alert1) !== categorizeAlert(alert2)) {
    return false;
  }
  if (alert1.severity !== alert2.severity) {
    return false;
  }

  // Extract key terms from titles
  const getKeyTerms = (title: string): Set<string> => {
    const stopWords = new Set(['de', 'en', 'el', 'la', 'los', 'las', 'un', 'una', 'y', 'o', 'a', 'the', 'in', 'on', 'at', 'of', 'and', 'or']);
    return new Set(
      title
        .toLowerCase()
        .split(/\s+/)
        .filter(word => word.length > 3 && !stopWords.has(word))
    );
  };

  const terms1 = getKeyTerms(alert1.title);
  const terms2 = getKeyTerms(alert2.title);

  // Calculate similarity: intersection / union
  const intersection = new Set([...terms1].filter(x => terms2.has(x)));
  const union = new Set([...terms1, ...terms2]);

  const similarity = intersection.size / union.size;

  return similarity > 0.5; // 50% similarity threshold
}

/**
 * Group alerts by time periods
 */
export function groupAlertsByTime(alerts: NotificationData[]): AlertGroup[] {
  const groups: Map<TimeGroup, NotificationData[]> = new Map();

  alerts.forEach(alert => {
    const timeGroup = getTimeGroup(alert.timestamp);
    if (!groups.has(timeGroup)) {
      groups.set(timeGroup, []);
    }
    groups.get(timeGroup)!.push(alert);
  });

  const timeOrder: TimeGroup[] = ['today', 'yesterday', 'this_week', 'older'];

  return timeOrder
    .filter(key => groups.has(key))
    .map(key => {
      const groupAlerts = groups.get(key)!;
      const highestSeverity = getHighestSeverity(groupAlerts);

      return {
        id: `time-${key}`,
        type: 'time' as const,
        key,
        title: getTimeGroupName(key),
        count: groupAlerts.length,
        severity: highestSeverity,
        alerts: groupAlerts,
      };
    });
}

/**
 * Group alerts by category
 */
export function groupAlertsByCategory(alerts: NotificationData[]): AlertGroup[] {
  const groups: Map<AlertCategory, NotificationData[]> = new Map();

  alerts.forEach(alert => {
    const category = categorizeAlert(alert);
    if (!groups.has(category)) {
      groups.set(category, []);
    }
    groups.get(category)!.push(alert);
  });

  // Sort by count (descending)
  const sortedCategories = Array.from(groups.entries())
    .sort((a, b) => b[1].length - a[1].length);

  return sortedCategories.map(([category, groupAlerts]) => {
    const highestSeverity = getHighestSeverity(groupAlerts);

    return {
      id: `category-${category}`,
      type: 'category' as const,
      key: category,
      title: `${getCategoryIcon(category)} ${getCategoryName(category)}`,
      count: groupAlerts.length,
      severity: highestSeverity,
      alerts: groupAlerts,
    };
  });
}

/**
 * Group similar alerts together
 */
export function groupSimilarAlerts(alerts: NotificationData[]): AlertGroup[] {
  const groups: AlertGroup[] = [];
  const processed = new Set<string>();

  alerts.forEach(alert => {
    if (processed.has(alert.id)) {
      return;
    }

    // Find similar alerts
    const similarAlerts = alerts.filter(other =>
      !processed.has(other.id) && areAlertsSimilar(alert, other)
    );

    if (similarAlerts.length > 1) {
      // Create a group
      similarAlerts.forEach(a => processed.add(a.id));

      const category = categorizeAlert(alert);
      const highestSeverity = getHighestSeverity(similarAlerts);

      groups.push({
        id: `similar-${alert.id}`,
        type: 'similarity',
        key: `${category}-${alert.severity}`,
        title: `${similarAlerts.length} alertas de ${getCategoryName(category).toLowerCase()}`,
        count: similarAlerts.length,
        severity: highestSeverity,
        alerts: similarAlerts,
      });
    } else {
      // Single alert, add as individual group
      processed.add(alert.id);
      groups.push({
        id: `single-${alert.id}`,
        type: 'similarity',
        key: alert.id,
        title: alert.title,
        count: 1,
        severity: alert.severity as AlertSeverity,
        alerts: [alert],
      });
    }
  });

  return groups;
}

/**
 * Get highest severity from a list of alerts
 */
export function getHighestSeverity(alerts: NotificationData[]): AlertSeverity {
  const severityOrder: AlertSeverity[] = ['urgent', 'high', 'medium', 'low'];

  for (const severity of severityOrder) {
    if (alerts.some(alert => alert.severity === severity)) {
      return severity;
    }
  }

  return 'low';
}

/**
 * Sort alerts by severity and timestamp
 */
export function sortAlerts(alerts: NotificationData[]): NotificationData[] {
  const severityOrder: Record<AlertSeverity, number> = {
    urgent: 4,
    high: 3,
    medium: 2,
    low: 1,
  };

  return [...alerts].sort((a, b) => {
    // First by severity
    const severityDiff = severityOrder[b.severity as AlertSeverity] - severityOrder[a.severity as AlertSeverity];
    if (severityDiff !== 0) {
      return severityDiff;
    }

    // Then by timestamp (newest first)
    return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
  });
}

/**
 * Filter alerts based on criteria
 */
export function filterAlerts(
  alerts: NotificationData[],
  filters: AlertFilters,
  snoozedAlerts: Map<string, SnoozedAlert>
): NotificationData[] {
  return alerts.filter(alert => {
    // Filter by severity
    if (filters.severities.length > 0 && !filters.severities.includes(alert.severity as AlertSeverity)) {
      return false;
    }

    // Filter by category
    if (filters.categories.length > 0) {
      const category = categorizeAlert(alert);
      if (!filters.categories.includes(category)) {
        return false;
      }
    }

    // Filter by time range
    if (filters.timeRange !== 'all') {
      const timeGroup = getTimeGroup(alert.timestamp);
      if (timeGroup !== filters.timeRange) {
        return false;
      }
    }

    // Filter by search text
    if (filters.search.trim()) {
      const searchLower = filters.search.toLowerCase();
      const searchableText = `${alert.title} ${alert.message}`.toLowerCase();
      if (!searchableText.includes(searchLower)) {
        return false;
      }
    }

    // Filter snoozed alerts
    if (!filters.showSnoozed) {
      const snoozed = snoozedAlerts.get(alert.id);
      if (snoozed && snoozed.until > Date.now()) {
        return false;
      }
    }

    return true;
  });
}

/**
 * Check if alert is snoozed
 */
export function isAlertSnoozed(alertId: string, snoozedAlerts: Map<string, SnoozedAlert>): boolean {
  const snoozed = snoozedAlerts.get(alertId);
  if (!snoozed) {
    return false;
  }

  if (snoozed.until <= Date.now()) {
    return false;
  }

  return true;
}

/**
 * Get time remaining for snoozed alert
 */
export function getSnoozedTimeRemaining(alertId: string, snoozedAlerts: Map<string, SnoozedAlert>): string | null {
  const snoozed = snoozedAlerts.get(alertId);
  if (!snoozed || snoozed.until <= Date.now()) {
    return null;
  }

  const remaining = snoozed.until - Date.now();
  const hours = Math.floor(remaining / (1000 * 60 * 60));
  const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));

  if (hours > 24) {
    const days = Math.floor(hours / 24);
    return `${days}d`;
  }
  if (hours > 0) {
    return `${hours}h ${minutes}m`;
  }
  return `${minutes}m`;
}

/**
 * Calculate snooze timestamp based on duration
 */
export function calculateSnoozeUntil(duration: '15min' | '1hr' | '4hr' | 'tomorrow' | number): number {
  const now = Date.now();

  if (typeof duration === 'number') {
    return now + duration;
  }

  switch (duration) {
    case '15min':
      return now + 15 * 60 * 1000;
    case '1hr':
      return now + 60 * 60 * 1000;
    case '4hr':
      return now + 4 * 60 * 60 * 1000;
    case 'tomorrow': {
      const tomorrow = new Date();
      tomorrow.setDate(tomorrow.getDate() + 1);
      tomorrow.setHours(9, 0, 0, 0); // 9 AM tomorrow
      return tomorrow.getTime();
    }
    default:
      return now + 60 * 60 * 1000; // default 1 hour
  }
}

/**
 * Get contextual action for alert type
 */
export interface ContextualAction {
  label: string;
  icon: string;
  variant: 'primary' | 'secondary' | 'outline';
  action: string; // action identifier
  route?: string; // navigation route
}

export function getContextualActions(alert: NotificationData): ContextualAction[] {
  const category = categorizeAlert(alert);
  const text = `${alert.title} ${alert.message}`.toLowerCase();

  const actions: ContextualAction[] = [];

  // Category-specific actions
  if (category === 'inventory') {
    if (text.includes('bajo') || text.includes('low')) {
      actions.push({
        label: 'Ordenar Stock',
        icon: '🛒',
        variant: 'primary',
        action: 'order_stock',
        route: '/app/procurement',
      });
    }
    if (text.includes('caduca') || text.includes('expir')) {
      actions.push({
        label: 'Planificar Uso',
        icon: '📅',
        variant: 'primary',
        action: 'plan_usage',
        route: '/app/production',
      });
    }
  }

  if (category === 'equipment') {
    actions.push({
      label: 'Programar Mantenimiento',
      icon: '🔧',
      variant: 'primary',
      action: 'schedule_maintenance',
      route: '/app/operations/maquinaria',
    });
  }

  if (category === 'orders') {
    if (text.includes('retraso') || text.includes('delayed')) {
      actions.push({
        label: 'Contactar Cliente',
        icon: '📞',
        variant: 'primary',
        action: 'contact_customer',
      });
    }
  }

  if (category === 'production') {
    actions.push({
      label: 'Ver Producción',
      icon: '🏭',
      variant: 'secondary',
      action: 'view_production',
      route: '/app/production',
    });
  }

  // Always add generic view details action
  actions.push({
    label: 'Ver Detalles',
    icon: '👁️',
    variant: 'outline',
    action: 'view_details',
  });

  return actions;
}

/**
 * Search alerts with highlighting
 */
export interface SearchMatch {
  alert: NotificationData;
  highlights: {
    title: boolean;
    message: boolean;
  };
}

export function searchAlerts(alerts: NotificationData[], query: string): SearchMatch[] {
  if (!query.trim()) {
    return alerts.map(alert => ({
      alert,
      highlights: { title: false, message: false },
    }));
  }

  const searchLower = query.toLowerCase();

  return alerts
    .filter(alert => {
      const titleMatch = alert.title.toLowerCase().includes(searchLower);
      const messageMatch = alert.message.toLowerCase().includes(searchLower);
      return titleMatch || messageMatch;
    })
    .map(alert => ({
      alert,
      highlights: {
        title: alert.title.toLowerCase().includes(searchLower),
        message: alert.message.toLowerCase().includes(searchLower),
      },
    }));
}

/**
 * Get alert statistics
 */
export interface AlertStats {
  total: number;
  bySeverity: Record<AlertSeverity, number>;
  byCategory: Record<AlertCategory, number>;
  unread: number;
  snoozed: number;
}

export function getAlertStatistics(
  alerts: NotificationData[],
  snoozedAlerts: Map<string, SnoozedAlert>
): AlertStats {
  const stats: AlertStats = {
    total: alerts.length,
    bySeverity: { urgent: 0, high: 0, medium: 0, low: 0 },
    byCategory: { inventory: 0, production: 0, orders: 0, equipment: 0, quality: 0, suppliers: 0, other: 0 },
    unread: 0,
    snoozed: 0,
  };

  alerts.forEach(alert => {
    stats.bySeverity[alert.severity as AlertSeverity]++;
    stats.byCategory[categorizeAlert(alert)]++;

    if (!alert.read) {
      stats.unread++;
    }

    if (isAlertSnoozed(alert.id, snoozedAlerts)) {
      stats.snoozed++;
    }
  });

  return stats;
}
