/**
 * Ports (driven interfaces). Domain owns them; infrastructure implements them.
 */
import type { NewUser, User } from './user.js';
import type { Session } from './session.js';
import type { PasswordResetToken } from './password-reset.js';

export interface PasswordHasher {
  hash(plain: string): Promise<string>;
  verify(hash: string, plain: string): Promise<boolean>;
}

export interface UserRepository {
  create(user: NewUser): Promise<User>;
  findByEmail(email: string): Promise<(User & { passwordHash: string }) | undefined>;
  findById(id: string): Promise<User | undefined>;
  listUsers(params?: {
    limit?: number;
    offset?: number;
    role?: string;
    q?: string;
  }): Promise<{ items: User[]; total: number }>;
  updateUser(id: string, patch: { role?: string; passwordHash?: string }): Promise<User>;
  deleteUser(id: string): Promise<void>;
}

export interface SessionRepository {
  /** Stores only the token hash, never the raw token. */
  create(userId: string, tokenHash: string, expiresAt: Date): Promise<Session>;
  /** Revokes by token hash. Returns true when a live session was revoked. */
  revokeByTokenHash(tokenHash: string): Promise<boolean>;
}

export interface PasswordResetTokenRepository {
  invalidateAllForUser(userId: string): Promise<void>;
  create(input: {
    userId: string;
    tokenHash: string;
    expiresAt: Date;
    requestIp?: string;
    requestUserAgent?: string;
  }): Promise<PasswordResetToken>;
  findByTokenHash(tokenHash: string): Promise<PasswordResetToken | undefined>;
  markUsed(id: string): Promise<void>;
}

export interface ResetRateLimiter {
  /** Returns true if the action should proceed; false if it should be silently rejected. */
  allow(key: string): Promise<boolean>;
}

export interface PasswordResetMailer {
  /** Optional readiness check; absent in test doubles and legacy adapters. */
  isConfigured?: () => boolean;
  assertReady?: () => Promise<void>;
  sendPasswordReset(input: { email: string; resetUrl: string; locale?: string }): Promise<void>;
}

/** Sends a welcome email when an account is created. Best-effort: callers must
 * swallow errors so a delivery failure never blocks registration. */
export interface WelcomeMailer {
  sendWelcome(input: { email: string; name?: string }): Promise<void>;
}
