/**
 * Message Repository Port Interface
 *
 * Port for Message aggregate operations.
 * Implementations (Drizzle, etc.) are adapters.
 *
 * Messages persist agent questions for users to query and respond later.
 * Supports threading via parentMessageId for response linking.
 */

import type { Message } from '../schema.js';

/**
 * Message sender/recipient type.
 */
export type MessageParticipantType = 'agent' | 'user';

/**
 * Message type.
 */
export type MessageType = 'question' | 'info' | 'error' | 'response';

/**
 * Message status.
 */
export type MessageStatus = 'pending' | 'read' | 'responded';

/**
 * Data for creating a new message.
 * Omits system-managed fields (id, createdAt, updatedAt).
 */
export interface CreateMessageData {
  senderType: MessageParticipantType;
  senderId?: string | null;
  recipientType: MessageParticipantType;
  recipientId?: string | null;
  type?: MessageType;
  content: string;
  requiresResponse?: boolean;
  status?: MessageStatus;
  parentMessageId?: string | null;
}

/**
 * Data for updating a message.
 * Partial of create data - all fields optional.
 */
export type UpdateMessageData = Partial<CreateMessageData>;

/**
 * Message Repository Port
 *
 * Defines operations for the Message aggregate.
 * Enables message persistence for agent-user communication.
 */
export interface MessageRepository {
  /**
   * Create a new message.
   * Generates id and sets timestamps automatically.
   */
  create(data: CreateMessageData): Promise<Message>;

  /**
   * Find a message by its ID.
   * Returns null if not found.
   */
  findById(id: string): Promise<Message | null>;

  /**
   * Find messages by sender.
   * @param type - 'agent' or 'user'
   * @param id - Optional sender ID (agent ID if type='agent', omit for user)
   * Returns messages ordered by createdAt DESC.
   */
  findBySender(type: MessageParticipantType, id?: string): Promise<Message[]>;

  /**
   * Find messages by recipient.
   * @param type - 'agent' or 'user'
   * @param id - Optional recipient ID (agent ID if type='agent', omit for user)
   * Returns messages ordered by createdAt DESC.
   */
  findByRecipient(type: MessageParticipantType, id?: string): Promise<Message[]>;

  /**
   * Find all pending messages for user.
   * Returns messages where recipientType='user' and status='pending'.
   * Ordered by createdAt DESC.
   */
  findPendingForUser(): Promise<Message[]>;

  /**
   * Find all messages requiring a response.
   * Returns messages where requiresResponse=true and status='pending'.
   * Ordered by createdAt DESC.
   */
  findRequiringResponse(): Promise<Message[]>;

  /**
   * Find all replies to a message.
   * @param parentMessageId - The ID of the parent message
   * Returns messages ordered by createdAt DESC.
   */
  findReplies(parentMessageId: string): Promise<Message[]>;

  /**
   * Update a message.
   * Throws if message not found.
   * Updates updatedAt timestamp automatically.
   */
  update(id: string, data: UpdateMessageData): Promise<Message>;

  /**
   * Delete a message.
   * Throws if message not found.
   */
  delete(id: string): Promise<void>;
}
