/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.data.api.dto

import kotlinx.serialization.Serializable

/**
 * The mobile bearer-auth wire shapes (PLAN.md §4.1). Field names match the
 * backend's `auth/mobile` controller and `/auth/me` exactly; every DTO ignores
 * unknown keys (NetworkModule's lenient Json), so additive backend fields are
 * safe (§8, recorded for M1).
 */

/**
 * `POST /auth/mobile/login` body (trusted-devices contract, TRUSTED_DEVICES_MFA.md).
 * [code] is only sent on the 2FA retry; [recoveryCode] is its single-use fallback
 * (sent instead of [code]). [trustDevice] asks the server to remember this device so
 * future logins skip the second factor — on success the response carries a
 * [MobileTokenResponse.trustToken] the app stores and replays via `X-Trust-Token`.
 * [device_name] labels the resulting trusted-device / session row (snake_case to
 * match the backend field exactly).
 */
@Serializable
data class MobileLoginRequest(
    val username: String,
    val password: String,
    val code: String? = null,
    val recoveryCode: String? = null,
    val trustDevice: Boolean? = null,
    val device_name: String? = null,
)

/** `POST /auth/mobile/refresh` body. */
@Serializable
data class MobileRefreshRequest(val refreshToken: String)

/** `POST /auth/mobile/logout` body — revoke this session or (with [all]) every session. */
@Serializable
data class MobileLogoutRequest(
    val refreshToken: String? = null,
    val all: Boolean? = null,
)

/**
 * Success payload from login and refresh: the token pair, the access lifetime
 * (a zeit/ms duration string, e.g. "15m"), and the safe (secret-stripped) user.
 *
 * Login additionally carries the trusted-device outcome when `trustDevice` was set:
 * [trustToken] is the opaque token to persist + replay (present only when the trust
 * was accepted), or [trustLimitReached] + [devices] when the per-user cap blocked it
 * (the login itself still succeeded). Refresh never sets these.
 */
@Serializable
data class MobileTokenResponse(
    val accessToken: String,
    val refreshToken: String,
    val expiresIn: String? = null,
    val user: SafeUserDto,
    val trustToken: String? = null,
    val trustLimitReached: Boolean = false,
    val devices: List<TrustedDeviceDto> = emptyList(),
)

/** The minimal, non-sensitive user the app needs to render + gate the menu (§5). */
@Serializable
data class SafeUserDto(
    val id: Long,
    val username: String,
    val role: String,
)

/** `GET /auth/me` envelope — the role source, re-validated on resume (§4.3). */
@Serializable
data class MeResponse(val user: SafeUserDto)

/**
 * The `401 { totpRequired: true }` body the single-request 2FA flow returns when
 * an account has TOTP on and no/invalid code accompanied the login (§4.1). Parsed
 * from the error body since it is not a 2xx response.
 */
@Serializable
data class TotpRequiredError(
    val totpRequired: Boolean = false,
    val message: String? = null,
)
