/**
 * The auth contract.
 *
 * Written as the shape a real identity service would return, not as the shape
 * the current mock happens to have. When /api/auth/* is repointed at Node,
 * Nest, Spring or anything else, this file is the negotiation artifact and the
 * UI below it does not move.
 */

export type UserRole = 'owner' | 'manager' | 'analyst';

/** The authenticated principal. Never contains credentials. */
export interface AuthUser {
  id: string;
  email: string;
  name: string;
  role: UserRole;
  /** Merchant/tenant this user belongs to. */
  organisation: string;
}

/** What the client is allowed to know about its own session. */
export interface AuthSession {
  user: AuthUser;
  /** ISO-8601. The client uses this only to display, never to authorise. */
  expiresAt: string;
}

export interface LoginCredentials {
  email: string;
  password: string;
  /**
   * Long-lived cookie vs browser-session cookie. Sent to the server because
   * cookie lifetime is a server decision — the client cannot be trusted to
   * enforce its own expiry.
   */
  rememberMe: boolean;
}

/**
 * Field-addressed failures, so the form can put the message on the input that
 * caused it rather than dumping everything into a banner.
 *
 * `form` covers anything not attributable to one field (network, 500s).
 */
export type LoginErrorField = 'email' | 'password' | 'form';

export interface LoginError {
  field: LoginErrorField;
  message: string;
}

/**
 * The result of an attempt. A discriminated union rather than
 * `{user?, error?}`: the caller cannot forget to check, because there is no
 * shape where both are present.
 */
export type LoginResult =
  | {ok: true; session: AuthSession}
  | {ok: false; error: LoginError};
