//! PM-26 XRPC read endpoints (appview query layer).
//!
//! All read endpoints are backed by the SQLite projection — records in
//! `record_json`, handles in `identities`, profiles in `profiles` — so the read
//! path needs no Hydrant handle. Endpoints mount via `jacquard-axum`'s
//! [`IntoRouter`] and share [`AppState`] (SQLite pool + identity resolver + bsky
//! client).
//!
//! Scope (PM-26): read endpoints only. Authenticated `getSession`/viewer state is
//! PM-27; the client appview/session UX is PM-45; the SSR bridge is PM-46; the
//! PDS passthrough proxy is PM-47.

pub mod error;
pub mod state;
pub mod views;

mod actor;
mod graph;
mod library;

#[cfg(test)]
mod tests;

use std::sync::Arc;

use axum::Router;
use jacquard_axum::IntoRouter;
use jacquard_common::xrpc::XrpcEndpoint;
use polymodel_api::space_polymodel::{
    actor::{get_profile::GetProfileRequest, get_session::GetSessionRequest},
    graph::get_list::GetListRequest,
    library::{
        get_author_things::GetAuthorThingsRequest, get_feed::GetFeedRequest,
        get_model::GetModelRequest, get_thing::GetThingRequest, search_things::SearchThingsRequest,
    },
};

use self::state::AppState;

/// Build the appview XRPC router with the given state applied.
///
/// The returned `Router<()>` is merged with the Dioxus SSR router in `main`.
pub fn router(state: Arc<AppState>) -> Router {
    Router::new()
        .merge(GetThingRequest::into_router(library::get_thing))
        .merge(GetModelRequest::into_router(library::get_model))
        .merge(GetAuthorThingsRequest::into_router(
            library::get_author_things,
        ))
        .merge(GetFeedRequest::into_router(library::get_feed))
        .merge(SearchThingsRequest::into_router(library::search_things))
        .merge(GetListRequest::into_router(graph::get_list))
        .merge(GetProfileRequest::into_router(actor::get_profile))
        // getSession takes no parameters, so it bypasses ExtractXrpc (which
        // decodes the query string; a unit-struct request from an empty query is
        // rejected by serde_html_form). Identity comes from the session, PM-27.
        .route(
            GetSessionRequest::PATH,
            axum::routing::get(actor::get_session),
        )
        .with_state(state)
}
