/**
 * Application Use Case: MarkNotificationReadUseCase
 * 
 * Marks a notification as read.
 */

import type { AsyncUseCase } from '@core/shared/application';
import type { INotificationRepository } from '../../domain/repositories/INotificationRepository';
import { NotificationDomainError } from '../../domain/errors/NotificationDomainError';
import type { Logger } from '@core/shared/application';

export interface MarkNotificationReadCommand {
  notificationId: string;
  recipientId: string; // For validation
}

export class MarkNotificationReadUseCase implements AsyncUseCase<MarkNotificationReadCommand, void> {
  constructor(
    private readonly notificationRepository: INotificationRepository,
    private readonly logger: Logger,
  ) {}

  async execute(command: MarkNotificationReadCommand): Promise<void> {
    this.logger.debug(`Attempting to mark notification ${command.notificationId} as read for recipient ${command.recipientId}`);
    try {
      const notification = await this.notificationRepository.findById(command.notificationId);
      
      if (!notification) {
        this.logger.warn(`Notification not found for ID: ${command.notificationId}`);
        throw new NotificationDomainError('Notification not found');
      }

      if (notification.recipientId !== command.recipientId) {
        this.logger.warn(`Unauthorized attempt to mark notification ${command.notificationId}. Recipient ID mismatch.`);
        throw new NotificationDomainError('Cannot mark another user\'s notification as read');
      }

      if (!notification.isUnread()) {
        this.logger.info(`Notification ${command.notificationId} is already read. Skipping update.`);
        return; // Already read, nothing to do
      }

      const updatedNotification = notification.markAsRead();
      await this.notificationRepository.update(updatedNotification);
      this.logger.info(`Notification ${command.notificationId} successfully marked as read.`);
    } catch (error) {
      this.logger.error(`Failed to mark notification ${command.notificationId} as read: ${error instanceof Error ? error.message : String(error)}`);
      throw error;
    }
  }
}

/**
 * Application Use Case: MarkAllNotificationsReadUseCase
 * 
 * Marks all notifications as read for a recipient.
 */
export class MarkAllNotificationsReadUseCase implements AsyncUseCase<string, void> {
  constructor(
    private readonly notificationRepository: INotificationRepository,
  ) {}

  async execute(recipientId: string): Promise<void> {
    await this.notificationRepository.markAllAsReadByRecipientId(recipientId);
  }
}

/**
 * Application Use Case: DismissNotificationUseCase
 * 
 * Dismisses a notification.
 */
export interface DismissNotificationCommand {
  notificationId: string;
  recipientId: string;
}

export class DismissNotificationUseCase implements AsyncUseCase<DismissNotificationCommand, void> {
  constructor(
    private readonly notificationRepository: INotificationRepository,
  ) {}

  async execute(command: DismissNotificationCommand): Promise<void> {
    const notification = await this.notificationRepository.findById(command.notificationId);
    
    if (!notification) {
      throw new NotificationDomainError('Notification not found');
    }

    if (notification.recipientId !== command.recipientId) {
      throw new NotificationDomainError('Cannot dismiss another user\'s notification');
    }

    if (notification.isDismissed()) {
      return; // Already dismissed
    }

    const updatedNotification = notification.dismiss();
    await this.notificationRepository.update(updatedNotification);
  }
}