use std::collections::HashSet;
use axum::routing::get;
use entertainarr_domain::tvshow::entity::{
FindTvShowResponse, ListTvShowResponse, TvShowWithSubscription,
};
use crate::entity::tvshow::{
TvShowAttributes, TvShowDocument, TvShowInclude, TvShowRelation, TvShowRelationships,
TvShowSource,
};
use crate::entity::tvshow_subscription::{
TvShowSubscriptionAttributes, TvShowSubscriptionDocument, TvShowSubscriptionEntity,
};
use crate::entity::{ApiResource, Couple, Relation};
use crate::server::handler::prelude::FromDomainResponse;
mod find;
mod subscription;
mod user_list;
pub fn create<S>() -> axum::Router<S>
where
S: crate::server::prelude::ServerState + Clone,
{
axum::Router::new()
.route("/tvshows/{tvshow_id}", get(find::handle::<S>))
.route(
"/users/me/tvshows",
get(user_list::handle::<S>).post(subscription::create::handle::<S>),
)
}
impl From<entertainarr_domain::tvshow::entity::TvShowSource> for TvShowSource {
fn from(value: entertainarr_domain::tvshow::entity::TvShowSource) -> Self {
match value {
entertainarr_domain::tvshow::entity::TvShowSource::Tmdb { tmdb_id } => {
TvShowSource::Tmdb { tmdb_id }
}
}
}
}
impl From<TvShowSource> for entertainarr_domain::tvshow::entity::TvShowSource {
fn from(value: TvShowSource) -> Self {
match value {
TvShowSource::Tmdb { tmdb_id } => {
entertainarr_domain::tvshow::entity::TvShowSource::Tmdb { tmdb_id }
}
}
}
}
impl From<entertainarr_domain::tvshow::entity::TvShow> for TvShowAttributes {
fn from(tvshow: entertainarr_domain::tvshow::entity::TvShow) -> Self {
Self {
source: tvshow.source.into(),
original_name: tvshow.original_name,
original_language: tvshow.original_language,
origin_country: tvshow.origin_country,
language: tvshow.language.into(),
name: tvshow.name,
overview: tvshow.overview,
tagline: tvshow.tagline,
poster_url: tvshow.poster_url,
backdrop_url: tvshow.backdrop_url,
homepage: tvshow.homepage,
first_air_date: tvshow.first_air_date,
in_production: tvshow.in_production,
adult: tvshow.adult,
created_at: tvshow.created_at,
updated_at: tvshow.updated_at,
}
}
}
impl From<entertainarr_domain::tvshow::entity::TvShowWithSubscription> for TvShowDocument {
fn from(value: entertainarr_domain::tvshow::entity::TvShowWithSubscription) -> Self {
let entertainarr_domain::tvshow::entity::TvShowWithSubscription {
tvshow,
subscription: _,
} = value;
Self {
id: tvshow.id,
kind: Default::default(),
relationships: TvShowRelationships {
subscription: Relation {
data: Some(TvShowSubscriptionEntity {
id: Couple(tvshow.id, 0),
kind: Default::default(),
}),
meta: (),
},
},
attributes: tvshow.into(),
}
}
}
impl ApiResource<Vec<TvShowDocument>, TvShowRelation> {
pub fn from_tvshow_subscription_list(list: Vec<TvShowWithSubscription>) -> Self {
let mut data = Vec::with_capacity(list.len());
list.into_iter().for_each(|item| {
data.push(TvShowDocument::from(item));
});
Self {
data,
includes: Vec::new(),
}
}
}
impl FromDomainResponse<FindTvShowResponse, TvShowInclude>
for ApiResource<TvShowDocument, TvShowRelation>
{
fn from_response(response: FindTvShowResponse, required: HashSet<TvShowInclude>) -> Self {
let data = TvShowDocument {
id: response.tvshow.id,
kind: Default::default(),
attributes: TvShowAttributes::from(response.tvshow),
relationships: TvShowRelationships {
subscription: Relation {
data: response.subscription.as_ref().map(|sub| {
TvShowSubscriptionEntity::new(Couple(sub.tvshow_id, sub.user_id))
}),
meta: (),
},
},
};
let mut includes = Vec::with_capacity(1);
if required.contains(&TvShowInclude::Subscription)
&& let Some(sub) = response.subscription
{
includes.push(TvShowRelation::TvShowSubscription(
TvShowSubscriptionDocument {
id: Couple(sub.tvshow_id, sub.user_id),
kind: Default::default(),
attributes: TvShowSubscriptionAttributes {
created_at: sub.created_at,
},
},
));
}
ApiResource { data, includes }
}
}
impl FromDomainResponse<ListTvShowResponse, TvShowInclude>
for ApiResource<Vec<TvShowDocument>, TvShowRelation>
{
fn from_response(response: ListTvShowResponse, required: HashSet<TvShowInclude>) -> Self {
let data = response
.tvshows
.into_iter()
.map(|tvshow| TvShowDocument {
id: tvshow.id,
kind: Default::default(),
relationships: TvShowRelationships {
subscription: Relation {
data: response.subscriptions.get(&tvshow.id).map(|sub| {
TvShowSubscriptionEntity::new(Couple(sub.tvshow_id, sub.user_id))
}),
meta: (),
},
},
attributes: tvshow.into(),
})
.collect();
let mut includes = Vec::default();
if required.contains(&TvShowInclude::Subscription) {
includes.extend(
response
.subscriptions
.into_values()
.map(|sub| TvShowRelation::TvShowSubscription(sub.into())),
);
}
ApiResource { data, includes }
}
}
impl From<entertainarr_domain::tvshow::entity::TvShowSubscription> for TvShowSubscriptionDocument {
fn from(value: entertainarr_domain::tvshow::entity::TvShowSubscription) -> Self {
TvShowSubscriptionDocument {
id: Couple(value.tvshow_id, value.user_id),
kind: Default::default(),
attributes: TvShowSubscriptionAttributes {
created_at: value.created_at,
},
}
}
}