// src/shared/utils/formatters.ts
// Formatting utilities for text and status display

import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

/**
 * Форматирует номер телефона для отображения в списках.
 * Всегда возвращает строку с ПРИНУДИТЕЛЬНЫМ ведущим плюсом: `+7 (911) ...`.
 * Если номер в базе уже с плюсом, не дублировать его.
 *
 * @param phone - Номер телефона (из БД в том формате, в котором он был сохранен)
 * @returns Номер телефона с обязательным ведущим плюсом
 */
export function formatPhoneNumber(phone: string): string {
  if (!phone) return '';
  // Если номер уже начинается с плюса, возвращаем как есть
  if (phone.startsWith('+')) {
    return phone;
  }
  // Иначе добавляем плюс в начало
  return '+' + phone;
}

/**
 * Форматирует номер телефона по мере ввода (Manual Control Mode).
 * Разрешить ввод только: `0-9`, ` `, `(`, `)`, `-`.
 * Любые другие символы (буквы, спецсимволы) вырезаются на лету.
 * Если в начале строки оказывается `+`, удалять его.
 *
 * @param phone - Строка ввода телефона
 * @returns Отфильтрованная строка БЕЗ начального плюса
 */
export function formatPhoneNumberAsYouType(phone: string): string {
  if (!phone) return '';
  
  // Убираем все плюсы сначала, чтобы никакой "залетный" плюс не просочился в стейт
  const withoutPlus = phone.replace(/\+/g, '');
  
  // Пропускаем только: цифры, пробелы, скобки (), дефисы -
  // Все остальные символы (буквы, спецсимволы) вырезаются
  return withoutPlus.replace(/[^\d\s\(\)\-]/g, '');
}

/**
 * Очищает номер телефона для `tel:` ссылок.
 * Используется ТОЛЬКО для `tel:` ссылок.
 * Очищает всё, кроме цифр, и добавляет один `+` в начало.
 *
 * @param phone - Номер телефона (может быть с плюсом или без, форматированным или нет)
 * @returns Номер в формате для tel: ссылки (например, "+79991234567")
 */
export function cleanPhoneNumber(phone: string): string {
  if (!phone) return '';
  
  // Очищаем всё, кроме цифр
  const cleaned = phone.replace(/[^\d]/g, '');
  
  if (!cleaned) return '';
  
  // Добавляем один плюс в начало для tel: ссылки
  return '+' + cleaned;
}

/**
 * Проверяет валидность номера телефона.
 * Сначала чистит строку через cleanPhoneNumber, затем проверяет длину (от 10 до 15 цифр).
 * Наличие скобок не должно проваливать валидацию.
 *
 * @param phone - Номер телефона (может быть с плюсом или без, форматированным или нет)
 * @returns true, если номер валиден, иначе false
 */
export function isValidPhoneNumber(phone: string): boolean {
  if (!phone) return false;
  
  // Сначала чистим строку через cleanPhoneNumber (оставляет только цифры и добавляет +)
  const cleaned = cleanPhoneNumber(phone);
  
  // Извлекаем только цифры для проверки длины
  const digitsOnly = cleaned.replace(/\D/g, '');
  
  // Проверяем длину (от 10 до 15 цифр)
  return digitsOnly.length >= 10 && digitsOnly.length <= 15;
}

/**
 * Truncate title to specified length + "..."
 */
export function truncateTitle(title: string, maxLength: number = 20): string {
  return title.length <= maxLength ? title : title.substring(0, maxLength) + '...';
}

/**
 * Truncate comment text to specified length + "..."
 */
export function truncateComment(text: string, maxLength: number = 30): string {
  return text.length <= maxLength ? text : text.substring(0, maxLength) + '...';
}

/**
 * Remove @mentions from content text using array of actually found names
 * Removes only occurrences of @Name that exist in the mentionedNames array
 */
export function removeMentionsFromContent(content: string, mentionedNames: string[]): string {
  let cleanedContent = content;
  
  // Remove only actual mentions found in database
  for (const name of mentionedNames) {
    cleanedContent = cleanedContent.replace('@' + name, '');
  }
  
  // Clean up extra whitespace
  return cleanedContent.replace(/\s+/g, ' ').trim();
}

/**
 * Returns Russian label for note status (lowercase for notifications)
 */
export function getStatusLabel(status: string): string {
  const statusMap: Record<string, string> = {
    'active': 'активно',
    'done': 'выполнено',
    'cancelled': 'отменено',
    'deferred': 'отложено',
  };
  return statusMap[status] || status;
}

/**
 * Returns Russian label for priority (lowercase for notifications)
 */
export function getPriorityLabel(priority: string): string {
  const priorityMap: Record<string, string> = {
    'low': 'низкий',
    'normal': 'обычный',
    'high': 'высокий',
  };
  return priorityMap[priority] || priority;
}

/**
 * Названия месяцев на русском для approval:created событий
 */
export const MONTH_NAMES = [
  'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
  'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
];

/**
 * Подготовить дополнительные поля для уведомления (транспортный уровень)
 * Добавляет поля isGrouped, monthName, link для approval:created событий
 * 
 * @param event - Тип события уведомления
 * @param data - Данные уведомления
 * @returns Объект с дополнительными полями для уведомления
 */
export function prepareNotificationFields(event: string, data: any): any {
  // Логика для Approval: добавляем isGrouped, monthName и link
  if (event === 'approval:created') {
    const month = data.month;
    const year = data.year;
    
    if (month && year) {
      const monthName = MONTH_NAMES[month - 1] || `Месяц ${month}`;
      
      return {
        isGrouped: true,
        monthName,
        link: data.link || { path: '/dashboard/schedule', query: { month, year } },
      };
    }
  }
  
  // Для остальных событий дополнительные поля не требуются
  return {};
}

/**
 * Единый источник правды для текста уведомлений
 * Объединяет логику из notifications.service.ts и NotificationBell.vue
 * 
 * @param event - Тип события уведомления
 * @param data - Данные уведомления (notification.data)
 * @returns Текст уведомления для отображения
 */
export function getNotificationMessage(event: string, data: any): string {
  const {
    authorName,
    performerName,
    performerRole,
    noteTitle,
    commentText,
    newStatus,
    newPriority,
    count,
    reminderTime,
    isBatch,
    message,
  } = data;

  // --- Формирование текстов для событий Notes ---

  // 1. Создание заметки: "{user} создал заметку: {title}"
  if (event === 'note:created' && authorName && noteTitle) {
    return `${authorName} создал заметку: ${noteTitle}`;
  }

  // 2. Упоминание: "{user} упомянул(а) вас в заметке {заголовок}"
  if (event === 'mention:notification' && noteTitle) {
    // Use performerName if provided, otherwise fall back to authorName
    const actualPerformerName = performerName || authorName;
    return `${actualPerformerName} упомянул(а) вас в заметке "${noteTitle}"`;
  }

  // 3. Комментарии: Батчинг и одиночные
  if (event === 'note:commented' && authorName && noteTitle) {
    if (isBatch && count && count > 1) {
      return `${authorName} добавил(а) ${count} комментария к заметке "${noteTitle}"`;
    } else {
      return `${authorName} добавил(а) комментарий к заметке "${noteTitle}"`;
    }
  }

  // 4. Изменение статуса: "{user} изменил статус заметки "{title}" на <b>{статус}</b>"
  if (event === 'note:status_changed' && authorName && noteTitle && newStatus) {
    const statusLabel = getStatusLabel(newStatus);
    return `${authorName} изменил статус заметки "${noteTitle}" на <b>${statusLabel}</b>`;
  }

  // 5. Изменение приоритета: "{user} изменил приоритет заметки "{title}" на <b>{приоритет}</b>"
  if (event === 'note:priority_changed' && authorName && noteTitle && newPriority) {
    const priorityLabel = getPriorityLabel(newPriority);
    return `${authorName} изменил приоритет заметки "${noteTitle}" на <b>${priorityLabel}</b>`;
  }

  // 6. Напоминание: "заметка: {title} сработало напоминание в {время}"
  if (event === 'note:reminder' && noteTitle && reminderTime) {
    return `Заметка: ${noteTitle} сработало напоминание в ${reminderTime}`;
  }

  // --- Логика для Approval ---

  if (event === 'approval:created' && data.isGrouped) {
    const monthName = data.monthName || MONTH_NAMES[(data.month || 1) - 1] || 'Месяц';
    const approvalCount = data.count || 1;
    if (approvalCount > 1) {
      return `Запрос на согласование · ${monthName} (${approvalCount})`;
    } else {
      return `Запрос на согласование · ${monthName}`;
    }
  }

  // --- Общий маппинг событий (из NotificationBell.vue) ---

  const eventMap: Record<string, string> = {
    // Notes events
    'note:deleted': 'Заметка удалена',
    
    // Schedule events
    'shift:update': 'Обновление смены',
    'shift:approved': 'Смена согласована',
    'shift:rejected': 'Смена отклонена',
    'shift:created': 'Новая смена',
    
    // Approval events
    'approval:resolved': 'Запрос согласован',
    'approval:rejected': 'Запрос отклонен',
    
    // Task events
    'task:created': 'Новая задача',
    'task:updated': 'Задача обновлена',
    'task:completed': 'Задача выполнена',
    'task:deleted': 'Задача удалена',
    
    // Personnel events
    'employee:hired': 'Сотрудник нанят',
    'employee:fired': 'Сотрудник уволен',
    'employee:rehired': 'Сотрудник принят повторно',
    
    // Operations events
    'checkin:created': 'Зарегистрирован гость',
    'checkout:created': 'Гость выписан',
    'linen:dispatched': 'Белье отправлено',
    
    // Paymaster events
    'paymaster:transaction': 'Операция в кассе',
    
    // System events
    'system:alert': 'Системное уведомление',
    'system:warning': 'Предупреждение',
    'system:error': 'Ошибка системы',
  };

  // Если есть message в data (например, для mention:notification или note:commented), возвращаем его
  if (message) {
    return message;
  }

  // Иначе используем маппинг событий
  return eventMap[event] || event;
}

/**
 * Возвращает операционный день (09:00-09:00) для указанной даты
 * Операционный день начинается в 09:00 и заканчивается в 09:00 следующего дня
 *
 * @param date - Дата для расчета (по умолчанию текущая)
 * @returns Строка в формате YYYY-MM-DD
 *
 * @example
 * getOperationalDay(new Date('2026-02-10T08:30:00')) // '2026-02-09'
 * getOperationalDay(new Date('2026-02-10T09:01:00')) // '2026-02-10'
 */
export function getOperationalDay(date?: Date): string {
  const d = date ? dayjs(date) : dayjs();
  
  // Используем часовой пояс Europe/Moscow
  const moscowTime = d.tz('Europe/Moscow');
  
  // Если время < 09:00, возвращаем предыдущий день
  if (moscowTime.hour() < 9) {
    return moscowTime.subtract(1, 'day').format('YYYY-MM-DD');
  }
  
  // Иначе возвращаем текущий день
  return moscowTime.format('YYYY-MM-DD');
}

/**
 * Возвращает русское название роли сотрудника
 *
 * @param role - Код роли (ADMIN, MANAGER, MAID, GOD)
 * @returns Русское название роли или пустую строку, если роль не указана
 */
export function getRoleLabel(role: string | null | undefined): string {
  const roleMap: Record<string, string> = {
    'ADMIN': 'Управляющий',
    'MANAGER': 'Администратор',
    'MAID': 'Горничная',
    'GOD': 'Владелец',
  };
  return role ? roleMap[role] || '' : '';
}
