// src/server/features/notes/notes.events.ts
// Event listeners for notes module - handles notifications and mentions

import { emitEvent, onEvent } from '@serverShared/lib/events';
import { loggerService } from '@serverShared/lib/logger';
import { parseMentions } from './lib/parser.service';
import { onNoteCreated, onNoteDeleted, onNoteStatusChanged, onNotePriorityChanged, onNotePublished, onMentionFound, onCommentCreated, onNoteReminder, onNoteContentUpdated } from './lib/notifier.service';
import { getEmployees } from '../personnel/personnel.service';
import type {
  NoteCreatedEvent,
  NoteUpdatedEvent,
  NoteDeletedEvent,
  CommentCreatedEvent,
} from '@shared/contracts/notes';

const eventsLogger = loggerService.get('SOCKET').child({ module: 'notes-events' });

/**
 * Helper function to get author name by ID
 */
async function getAuthorName(authorId: string): Promise<string> {
  try {
    const employees = await getEmployees('SYSTEM');
    const author = employees.find(emp => emp.id === authorId);
    return author ? author.fullName : 'Неизвестный';
  } catch (error) {
    eventsLogger.error(`Error fetching author name for ${authorId}:`, error);
    return 'Неизвестный';
  }
}

/**
 * Register all note event listeners
 * Call this once during application initialization
 */
export function registerNoteEventListeners(): void {
  // Listen for note:created events
  onEvent<NoteCreatedEvent>('note:created', async (data) => {
    try {
      eventsLogger.info(`[Events] note:created received for note ${data.noteId}`);
      const authorName = await getAuthorName(data.authorId);
      await onNoteCreated(data.note, authorName, data.content);
    } catch (error) {
      eventsLogger.error(`[Events] Error handling note:created:`, error);
    }
  });

  // Listen for note:updated events
  onEvent<NoteUpdatedEvent>('note:updated', async (data) => {
    try {
      eventsLogger.info(`[Events] note:updated received for note ${data.noteId}`);
      const authorName = await getAuthorName(data.authorId);
      
      // Get performer's name if provided (user who actually performed the action)
      const performerName = data.performerId ? await getAuthorName(data.performerId) : authorName;
 
      // Handle private → public transition
      if (data.isPublicChanged && data.newIsPublic === true && data.userId) {
        await onNotePublished(data.note, { id: data.userId, username: '', role: 'ADMIN' });
      }
 
      // Handle status change
      if (data.statusChanged && data.oldStatus !== undefined && data.userId) {
        await onNoteStatusChanged(data.note, data.oldStatus, { id: data.userId, username: '', role: 'ADMIN' });
      }
  
      // Handle priority change
      if (data.priorityChanged && data.oldPriority !== undefined && data.userId) {
        await onNotePriorityChanged(data.note, data.oldPriority, { id: data.userId, username: '', role: 'ADMIN' });
      }
  
      // Handle mentions (only if content was updated)
      if (data.contentUpdated) {
        if (data.userId) {
          await onNoteContentUpdated(data.note, { id: data.userId, username: '', role: 'ADMIN' } as any);
        }
        const mentionedNames = await parseMentions(data.note.content);
        if (mentionedNames.length > 0) {
          await onMentionFound(
            mentionedNames,
            data.noteId,
            authorName,
            performerName,
            data.note.title,
            data.note.content,
            data.note.lastCommentAt || undefined,
            data.note.authorId
          );
        }
      }
    } catch (error) {
      eventsLogger.error(`[Events] Error handling note:updated:`, error);
    }
  });

  // Listen for note:deleted events
  onEvent<NoteDeletedEvent>('note:deleted', async (data) => {
    try {
      eventsLogger.info(`[Events] note:deleted received for note ${data.noteId}`);
      await onNoteDeleted(data.noteId);
    } catch (error) {
      eventsLogger.error(`[Events] Error handling note:deleted:`, error);
    }
  });

  // Listen for comment:created events
  onEvent<CommentCreatedEvent>('comment:created', async (data) => {
    try {
      eventsLogger.info(`[Events] comment:created received for note ${data.noteId}`);
      eventsLogger.debug('[MENTIONS] comment:created event received:');
      eventsLogger.debug('[MENTIONS]   noteId:', data.noteId);
      eventsLogger.debug('[MENTIONS]   commentId:', data.commentId);
      eventsLogger.debug('[MENTIONS]   authorId (who wrote comment):', data.authorId);
      eventsLogger.debug('[MENTIONS]   noteTitle:', data.noteTitle);
      eventsLogger.debug('[MENTIONS]   isPublic:', data.isPublic);
      eventsLogger.debug('[MENTIONS]   content:', data.content);
      eventsLogger.debug('[MENTIONS]   lastCommentAt:', data.lastCommentAt);
      eventsLogger.debug('[MENTIONS]   lastCommentAt type:', typeof data.lastCommentAt);
      
      const authorName = await getAuthorName(data.authorId);
      eventsLogger.debug('[MENTIONS]   authorName (resolved):', authorName);
      
      eventsLogger.debug('[MENTIONS] About to call onCommentCreated...');
      // For comments, authorId is performer (the person writing the comment)
      // We pass authorName as both authorName and performerName for mentions in comments
      await onCommentCreated(data.noteId, data.authorId, authorName, data.noteTitle, data.isPublic, data.content, authorName, data.lastCommentAt);
      eventsLogger.debug('[MENTIONS] onCommentCreated completed successfully');
    } catch (error) {
      eventsLogger.error('[MENTIONS] Error in comment:created handler:', error);
      eventsLogger.error(`[Events] Error handling comment:created:`, error);
    }
  });

  // Listen for note:personal_reminder events
  onEvent<any>('note:personal_reminder', async (data) => {
    try {
      eventsLogger.info(`[Events] note:personal_reminder received for note ${data.noteId}, user ${data.userId}`);
      await onNoteReminder(data.noteId, data.title, data.userId);
    } catch (error) {
      eventsLogger.error(`[Events] Error handling note:personal_reminder:`, error);
    }
  });

  eventsLogger.info('[Events] Note event listeners registered successfully');
}

/**
 * Helper function to emit note:created event
 */
export async function emitNoteCreatedEvent(data: NoteCreatedEvent): Promise<void> {
  await emitEvent('note:created', data, data.authorId);
}

/**
 * Helper function to emit note:updated event
 */
export async function emitNoteUpdatedEvent(data: NoteUpdatedEvent): Promise<void> {
  await emitEvent('note:updated', data, data.userId ?? data.authorId);
}

/**
 * Helper function to emit note:deleted event
 */
export async function emitNoteDeletedEvent(data: NoteDeletedEvent): Promise<void> {
  await emitEvent('note:deleted', data);
}

/**
 * Helper function to emit comment:created event
 */
export async function emitCommentCreatedEvent(data: CommentCreatedEvent): Promise<void> {
  await emitEvent('comment:created', data, data.authorId);
}
