//! Plain Rust request/response types for server domain logic.
//!
//! No proto, no capnp — just Rust structs.

use crate::storage::StorageError;

// ── Domain Error ────────────────────────────────────────────────────────────

/// Errors returned by domain service methods.
#[derive(thiserror::Error, Debug)]
pub enum DomainError {
    #[error("identity key must be exactly 32 bytes, got {0}")]
    InvalidIdentityKey(usize),

    #[error("key package must not be empty")]
    EmptyPackage,

    #[error("key package exceeds max size ({0} bytes)")]
    PackageTooLarge(usize),

    #[error("hybrid public key must not be empty")]
    EmptyHybridKey,

    #[error("username must not be empty")]
    EmptyUsername,

    #[error("blob hash must be exactly 32 bytes, got {0}")]
    BlobHashLength(usize),

    #[error("blob exceeds max size ({0} bytes)")]
    BlobTooLarge(u64),

    #[error("SHA-256 of uploaded data does not match blob hash")]
    BlobHashMismatch,

    #[error("blob not found")]
    BlobNotFound,

    #[error("maximum {0} devices per identity")]
    DeviceLimit(usize),

    #[error("device not found")]
    DeviceNotFound,

    #[error("group not found")]
    GroupNotFound,

    #[error("bad parameters: {0}")]
    BadParams(String),

    #[error("I/O error: {0}")]
    Io(String),

    #[error("storage error: {0}")]
    Storage(#[from] StorageError),
}

// ── Auth ─────────────────────────────────────────────────────────────────────

/// Caller authentication context (resolved from session token).
#[derive(Debug, Clone)]
pub struct CallerAuth {
    /// Ed25519 identity key of the authenticated caller (32 bytes).
    pub identity_key: Vec<u8>,
    /// Session token bytes.
    pub token: Vec<u8>,
    /// Device ID (optional, for auditing).
    pub device_id: Option<Vec<u8>>,
}

/// OPAQUE registration start.
pub struct RegisterStartReq {
    pub username: String,
    pub request_bytes: Vec<u8>,
}

/// OPAQUE registration start response.
pub struct RegisterStartResp {
    pub response_bytes: Vec<u8>,
}

/// OPAQUE registration finish.
pub struct RegisterFinishReq {
    pub username: String,
    pub upload_bytes: Vec<u8>,
    pub identity_key: Vec<u8>,
}

/// OPAQUE registration finish response.
pub struct RegisterFinishResp {
    pub success: bool,
}

/// OPAQUE login start.
pub struct LoginStartReq {
    pub username: String,
    pub request_bytes: Vec<u8>,
}

/// OPAQUE login start response.
pub struct LoginStartResp {
    pub response_bytes: Vec<u8>,
}

/// OPAQUE login finish.
pub struct LoginFinishReq {
    pub username: String,
    pub finalization_bytes: Vec<u8>,
    pub identity_key: Vec<u8>,
}

/// OPAQUE login finish response containing the session token.
pub struct LoginFinishResp {
    pub session_token: Vec<u8>,
}

// ── Delivery ─────────────────────────────────────────────────────────────────

/// An envelope pairing a sequence number with an opaque payload.
#[derive(Debug, Clone)]
pub struct Envelope {
    pub seq: u64,
    pub data: Vec<u8>,
}

/// Request to enqueue a message for delivery to a recipient.
pub struct EnqueueReq {
    pub recipient_key: Vec<u8>,
    pub payload: Vec<u8>,
    pub channel_id: Vec<u8>,
    pub ttl_secs: u32,
}

/// Response from enqueue with the assigned sequence number.
pub struct EnqueueResp {
    pub seq: u64,
    pub delivery_proof: Vec<u8>,
}

/// Request to fetch (and drain) queued messages.
pub struct FetchReq {
    pub recipient_key: Vec<u8>,
    pub channel_id: Vec<u8>,
    pub limit: u32,
}

/// Response containing fetched message envelopes.
pub struct FetchResp {
    pub payloads: Vec<Envelope>,
}

/// Request to peek at queued messages without draining.
pub struct PeekReq {
    pub recipient_key: Vec<u8>,
    pub channel_id: Vec<u8>,
    pub limit: u32,
}

/// Response containing peeked message envelopes.
pub struct PeekResp {
    pub payloads: Vec<Envelope>,
}

/// Request to acknowledge messages up to a sequence number.
pub struct AckReq {
    pub recipient_key: Vec<u8>,
    pub channel_id: Vec<u8>,
    pub seq_up_to: u64,
}

/// Request to enqueue a message to multiple recipients at once.
pub struct BatchEnqueueReq {
    pub recipient_keys: Vec<Vec<u8>>,
    pub payload: Vec<u8>,
    pub channel_id: Vec<u8>,
    pub ttl_secs: u32,
}

/// Response from batch enqueue with one sequence number per recipient.
pub struct BatchEnqueueResp {
    pub seqs: Vec<u64>,
}

// ── Keys ─────────────────────────────────────────────────────────────────────

/// Request to upload an MLS KeyPackage.
pub struct UploadKeyPackageReq {
    pub identity_key: Vec<u8>,
    pub package: Vec<u8>,
}

/// Response containing the SHA-256 fingerprint of the uploaded KeyPackage.
#[derive(Debug)]
pub struct UploadKeyPackageResp {
    pub fingerprint: Vec<u8>,
}

/// Request to fetch a stored MLS KeyPackage.
pub struct FetchKeyPackageReq {
    pub identity_key: Vec<u8>,
}

/// Response containing the MLS KeyPackage (empty if not found).
pub struct FetchKeyPackageResp {
    pub package: Vec<u8>,
}

/// Request to upload a hybrid (ML-KEM-768) public key.
pub struct UploadHybridKeyReq {
    pub identity_key: Vec<u8>,
    pub hybrid_public_key: Vec<u8>,
}

/// Request to fetch a single hybrid public key.
pub struct FetchHybridKeyReq {
    pub identity_key: Vec<u8>,
}

/// Response containing a hybrid public key (empty if not found).
pub struct FetchHybridKeyResp {
    pub hybrid_public_key: Vec<u8>,
}

/// Request to batch-fetch hybrid public keys for multiple identities.
pub struct FetchHybridKeysReq {
    pub identity_keys: Vec<Vec<u8>>,
}

/// Response containing hybrid keys in the same order as the request.
pub struct FetchHybridKeysResp {
    pub keys: Vec<Vec<u8>>,
}

// ── Key Transparency / Revocation ────────────────────────────────────

/// Request to revoke an identity key in the Key Transparency log.
pub struct RevokeKeyReq {
    pub identity_key: Vec<u8>,
    pub reason: String,
}

/// Response from key revocation with the leaf index in the KT log.
pub struct RevokeKeyResp {
    pub success: bool,
    pub leaf_index: u64,
}

/// Request to check if an identity key has been revoked.
pub struct CheckRevocationReq {
    pub identity_key: Vec<u8>,
}

/// Response with revocation status, reason, and timestamp.
pub struct CheckRevocationResp {
    pub revoked: bool,
    pub reason: String,
    pub timestamp_ms: u64,
}

/// Request for a range of Key Transparency audit log entries.
pub struct AuditKeyTransparencyReq {
    pub start: u64,
    pub end: u64,
}

/// A single entry in the KT audit log.
pub struct AuditLogEntry {
    pub index: u64,
    pub leaf_hash: Vec<u8>,
}

/// Response containing KT audit log entries, tree size, and root hash.
pub struct AuditKeyTransparencyResp {
    pub entries: Vec<AuditLogEntry>,
    pub tree_size: u64,
    pub root: Vec<u8>,
}

// ── Channel ──────────────────────────────────────────────────────────────────

/// Request to create a 1:1 DM channel with a peer.
pub struct CreateChannelReq {
    pub peer_key: Vec<u8>,
}

/// Response with the channel ID and whether it was newly created.
#[derive(Debug)]
pub struct CreateChannelResp {
    pub channel_id: Vec<u8>,
    pub was_new: bool,
}

// ── User ─────────────────────────────────────────────────────────────────────

/// Request to resolve a username to an identity key.
pub struct ResolveUserReq {
    pub username: String,
}

/// Response with the identity key and KT inclusion proof.
pub struct ResolveUserResp {
    pub identity_key: Vec<u8>,
    pub inclusion_proof: Vec<u8>,
}

/// Request to reverse-resolve an identity key to a username.
pub struct ResolveIdentityReq {
    pub identity_key: Vec<u8>,
}

/// Response with the resolved username (empty if unknown).
pub struct ResolveIdentityResp {
    pub username: String,
}

// ── Blob ─────────────────────────────────────────────────────────────────────

/// Request to upload a blob chunk. The blob is identified by its SHA-256 hash.
pub struct UploadBlobReq {
    pub blob_hash: Vec<u8>,
    pub chunk: Vec<u8>,
    pub offset: u64,
    pub total_size: u64,
    pub mime_type: String,
}

/// Response from blob upload containing the blob ID (same as hash).
pub struct UploadBlobResp {
    pub blob_id: Vec<u8>,
}

/// Request to download a chunk of a stored blob.
pub struct DownloadBlobReq {
    pub blob_id: Vec<u8>,
    pub offset: u64,
    pub length: u32,
}

/// Response containing the requested blob chunk and metadata.
pub struct DownloadBlobResp {
    pub chunk: Vec<u8>,
    pub total_size: u64,
    pub mime_type: String,
}

// ── Device ───────────────────────────────────────────────────────────────────

/// Request to register a new device for the caller's identity.
pub struct RegisterDeviceReq {
    pub device_id: Vec<u8>,
    pub device_name: String,
}

/// Response from device registration.
pub struct RegisterDeviceResp {
    pub success: bool,
}

/// Metadata about a registered device.
pub struct DeviceInfo {
    pub device_id: Vec<u8>,
    pub device_name: String,
    pub registered_at: u64,
}

/// Response listing all registered devices.
pub struct ListDevicesResp {
    pub devices: Vec<DeviceInfo>,
}

/// Request to revoke (remove) a registered device.
pub struct RevokeDeviceReq {
    pub device_id: Vec<u8>,
}

/// Response from device revocation.
pub struct RevokeDeviceResp {
    pub success: bool,
}

// ── Group metadata ───────────────────────────────────────────────────

/// Server-side group metadata.
pub struct GroupMetadata {
    pub group_id: Vec<u8>,
    pub name: String,
    pub description: String,
    pub avatar_hash: Vec<u8>,
    pub creator_key: Vec<u8>,
    pub created_at: u64,
}

/// Request to update group metadata (name, description, avatar).
pub struct UpdateGroupMetadataReq {
    pub group_id: Vec<u8>,
    pub name: String,
    pub description: String,
    pub avatar_hash: Vec<u8>,
}

/// Request to list members of a group.
pub struct ListGroupMembersReq {
    pub group_id: Vec<u8>,
}

/// A group member with resolved username.
pub struct GroupMemberInfo {
    pub identity_key: Vec<u8>,
    pub username: String,
    pub joined_at: u64,
}

/// Response listing group members.
pub struct ListGroupMembersResp {
    pub members: Vec<GroupMemberInfo>,
}

// ── Moderation ───────────────────────────────────────────────────────────────

/// Request to submit an encrypted abuse report.
pub struct ReportMessageReq {
    pub encrypted_report: Vec<u8>,
    pub conversation_id: Vec<u8>,
    pub reporter_identity: Vec<u8>,
}

/// Response from report submission.
pub struct ReportMessageResp {
    pub accepted: bool,
}

/// Request to ban a user. `duration_secs = 0` means permanent.
pub struct BanUserReq {
    pub identity_key: Vec<u8>,
    pub reason: String,
    pub duration_secs: u64,
}

/// Response from ban operation.
pub struct BanUserResp {
    pub success: bool,
}

/// Request to unban a user.
pub struct UnbanUserReq {
    pub identity_key: Vec<u8>,
}

/// Response from unban operation.
pub struct UnbanUserResp {
    pub success: bool,
}

/// Request to list abuse reports with pagination.
pub struct ListReportsReq {
    pub limit: u32,
    pub offset: u32,
}

/// A stored abuse report entry.
pub struct ReportEntry {
    pub id: u64,
    pub encrypted_report: Vec<u8>,
    pub conversation_id: Vec<u8>,
    pub reporter_identity: Vec<u8>,
    pub timestamp: u64,
}

/// Response containing paginated abuse reports.
pub struct ListReportsResp {
    pub reports: Vec<ReportEntry>,
}

/// A banned user entry with expiration info.
pub struct BannedUserEntry {
    pub identity_key: Vec<u8>,
    pub reason: String,
    pub banned_at: u64,
    pub expires_at: u64,
}

/// Response listing all currently banned users.
pub struct ListBannedResp {
    pub users: Vec<BannedUserEntry>,
}

// ── P2P ──────────────────────────────────────────────────────────────────────

/// Request to publish a P2P endpoint (iroh node address).
pub struct PublishEndpointReq {
    pub identity_key: Vec<u8>,
    pub node_addr: Vec<u8>,
}

/// Request to resolve a P2P endpoint for an identity.
pub struct ResolveEndpointReq {
    pub identity_key: Vec<u8>,
}

/// Response with the resolved P2P node address (empty if not published).
pub struct ResolveEndpointResp {
    pub node_addr: Vec<u8>,
}

/// Health-check response.
pub struct HealthResp {
    pub status: String,
}
