//! Recovery handlers — store/fetch/delete encrypted recovery bundles.

use std::sync::Arc;

use bytes::Bytes;
use prost::Message;
use quicproquo_proto::qpq::v1;
use quicproquo_rpc::method::{HandlerResult, RequestContext};

use crate::domain::recovery::RecoveryService;

use super::{domain_err, ServerState};

/// Store an encrypted recovery bundle (no auth required — recovery is pre-login).
pub async fn handle_store_recovery_bundle(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let req = match v1::StoreRecoveryBundleRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => {
            return HandlerResult::err(
                quicproquo_rpc::error::RpcStatus::BadRequest,
                &format!("decode: {e}"),
            )
        }
    };

    let svc = RecoveryService {
        store: Arc::clone(&state.store),
    };

    match svc.store_bundle(&req.token_hash, req.bundle, req.ttl_secs) {
        Ok(()) => {
            let proto = v1::StoreRecoveryBundleResponse { success: true };
            HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
        }
        Err(e) => domain_err(e),
    }
}

/// Fetch an encrypted recovery bundle (no auth required — recovery is pre-login).
pub async fn handle_fetch_recovery_bundle(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let req = match v1::FetchRecoveryBundleRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => {
            return HandlerResult::err(
                quicproquo_rpc::error::RpcStatus::BadRequest,
                &format!("decode: {e}"),
            )
        }
    };

    let svc = RecoveryService {
        store: Arc::clone(&state.store),
    };

    match svc.fetch_bundle(&req.token_hash) {
        Ok(bundle_opt) => {
            let proto = v1::FetchRecoveryBundleResponse {
                bundle: bundle_opt.unwrap_or_default(),
            };
            HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
        }
        Err(e) => domain_err(e),
    }
}

/// Delete an encrypted recovery bundle (no auth required — caller proves
/// knowledge of the token_hash).
pub async fn handle_delete_recovery_bundle(
    state: Arc<ServerState>,
    ctx: RequestContext,
) -> HandlerResult {
    let req = match v1::DeleteRecoveryBundleRequest::decode(ctx.payload) {
        Ok(r) => r,
        Err(e) => {
            return HandlerResult::err(
                quicproquo_rpc::error::RpcStatus::BadRequest,
                &format!("decode: {e}"),
            )
        }
    };

    let svc = RecoveryService {
        store: Arc::clone(&state.store),
    };

    match svc.delete_bundle(&req.token_hash) {
        Ok(deleted) => {
            let proto = v1::DeleteRecoveryBundleResponse { success: deleted };
            HandlerResult::ok(Bytes::from(proto.encode_to_vec()))
        }
        Err(e) => domain_err(e),
    }
}
