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

import kotlinx.serialization.Serializable

/**
 * The role-agnostic self-service ("me") wire shapes (PLAN.md §6.3, §6.4). Field
 * names match the backend's `account.controller` handlers exactly, surfaced for
 * the app under `/auth/me/account*`. Every DTO ignores unknown keys (NetworkModule's
 * lenient Json), so additive backend fields are safe (recorded for M1).
 */

/** `GET /auth/me/account` — the current account (any role). */
@Serializable
data class PlayerAccountDto(
    val id: Long = 0,
    val username: String = "",
    val role: String = "",
    val email: String? = null,
    val status: String? = null,
    val totp_enabled: Boolean = false,
    /** False for an SSO-provisioned account that has not set a password yet. */
    val has_password: Boolean = false,
)

/** `PATCH /auth/me/account/username` body. */
@Serializable
data class ChangeUsernameRequest(val username: String)

/** The `{ username }` returned by a successful username change. */
@Serializable
data class UsernameResponse(val username: String = "")

/**
 * `PATCH /auth/me/account/password` body. [currentPassword] is omitted only for an
 * SSO-provisioned account setting its initial password (has_password == false).
 */
@Serializable
data class ChangePasswordRequest(
    val newPassword: String,
    val currentPassword: String? = null,
)

/** Enrollment material from `POST /auth/me/account/totp/setup`. */
@Serializable
data class TotpSetupDto(
    val otpauthUrl: String? = null,
    /** QR code as a `data:image/png;base64,…` URL. */
    val qr: String? = null,
)

/** `POST /auth/me/account/totp/enable|disable` body — a current authenticator code. */
@Serializable
data class TotpCodeRequest(val code: String)

/**
 * Result of enabling/disabling 2FA. Enabling also returns the freshly generated
 * single-use [recoveryCodes] **once** (null on disable and for older backends) — the
 * app shows them for the user to save and never persists them.
 */
@Serializable
data class TotpStateDto(
    val totp_enabled: Boolean = false,
    val recoveryCodes: List<String>? = null,
)

// ── Trusted devices & recovery codes (TRUSTED_DEVICES_MFA.md) ───────────────

/**
 * An active trusted device (`GET /auth/me/trusted-devices`): a browser/app allowed
 * to skip the TOTP step at login. Never carries the token. Timestamps are ISO-8601
 * strings shown as-is (advisory display).
 */
@Serializable
data class TrustedDeviceDto(
    val id: Long = 0,
    val platform: String? = null,
    val deviceName: String? = null,
    val userAgent: String? = null,
    val createdAt: String? = null,
    val lastUsedAt: String? = null,
    val expiresAt: String? = null,
)

/** `POST /auth/me/trusted-devices` body — an optional friendly label. */
@Serializable
data class TrustDeviceRequest(val deviceName: String? = null)

/**
 * `POST /auth/me/trusted-devices` success (native): the opaque [trustToken] to store
 * and replay via `X-Trust-Token`. Web receives the token as a cookie and no body token.
 */
@Serializable
data class TrustDeviceResultDto(
    val trusted: Boolean = false,
    val trustToken: String? = null,
)

/**
 * `409 { error: "trusted_device_limit", devices }` from a trust attempt at the cap —
 * the app lists [devices] and asks the user to revoke one, then retry.
 */
@Serializable
data class TrustedDeviceLimitDto(
    val error: String? = null,
    val devices: List<TrustedDeviceDto> = emptyList(),
)

/** `DELETE /auth/me/trusted-devices/:id` — idempotent single-revoke result. */
@Serializable
data class RevokedFlagDto(val revoked: Boolean = false)

/** `DELETE /auth/me/trusted-devices` — count of devices untrusted ("untrust all"). */
@Serializable
data class RevokedCountDto(val revoked: Int = 0)

/** `GET /auth/me/account/recovery-codes/status` — remaining unused count only. */
@Serializable
data class RecoveryStatusDto(val remaining: Int = 0)

/** `POST /auth/me/account/recovery-codes/generate` body — password step-up. */
@Serializable
data class RecoveryGenerateRequest(val currentPassword: String? = null)

/** A fresh single-use recovery-code batch, returned **once** (generate + totp enable). */
@Serializable
data class RecoveryCodesDto(val recoveryCodes: List<String> = emptyList())

/** A linked external identity (`GET /auth/me/account/identities`). */
@Serializable
data class LinkedIdentityDto(
    val provider: String = "",
    val email: String? = null,
    val linked_at: String? = null,
)
