/*
    This file is part of jellything (https://codeberg.org/metamuffin/jellything)
    which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
    Copyright (C) 2026 metamuffin <metamuffin.org>
*/

use crate::locale::{Language, trs};
use jellycommon::api::{FilterProperty, NodeFilterSort, SortOrder, SortProperty};
use markup::RenderAttributeValue;

const SORT_CATS: &[(&str, &[(SortProperty, &str)])] = {
    use SortProperty::*;
    &[
        (
            "filter_sort.sort.general",
            &[(Title, "node.title"), (ReleaseDate, "node.release_date")],
        ),
        ("filter_sort.sort.media", &[(Duration, "media.duration")]),
        (
            "filter_sort.sort.rating",
            &[
                (RatingImdb, "rating.imdb"),
                (RatingTmdb, "rating.tmdb"),
                (RatingMetacritic, "rating.metacritic"),
                (RatingRottenTomatoes, "rating.rotten_tomatoes"),
                (RatingYoutubeFollowers, "rating.youtube_followers"),
                (RatingYoutubeLikes, "rating.youtube_likes"),
                (RatingYoutubeViews, "rating.youtube_views"),
                (RatingUser, "filter_sort.sort.rating.user"),
                (
                    RatingLikesDivViews,
                    "filter_sort.sort.rating.likes_div_views",
                ),
            ],
        ),
    ]
};
const FILTER_CATS: &[(&str, &[(FilterProperty, &str)])] = {
    use FilterProperty::*;
    &[
        (
            "filter_sort.filter.kind",
            &[
                (KindMovie, "kind.movie"),
                (KindVideo, "kind.video"),
                (KindShortFormVideo, "kind.short_form_video"),
                (KindMusic, "kind.music"),
                (KindCollection, "kind.collection"),
                (KindChannel, "kind.channel"),
                (KindShow, "kind.show"),
                (KindSeries, "kind.series"),
                (KindSeason, "kind.season"),
                (KindEpisode, "kind.episode"),
            ],
        ),
        (
            "filter_sort.filter.federation",
            &[
                (FederationLocal, "federation.local"),
                (FederationRemote, "federation.remote"),
            ],
        ),
        (
            "filter_sort.filter.watched",
            &[
                (Watched, "watched.watched"),
                (Unwatched, "watched.none"),
                (WatchProgress, "watched.progress"),
            ],
        ),
    ]
};

markup::define! {
    NodeFilterSortForm<'a>(f: &'a NodeFilterSort, lang: &'a Language) {
        details.filtersort[open=f.filter_kind.is_some() || f.sort_by.is_some()] {
            summary { "Filter and Sort" }
            form[method="GET", action=""] {
                fieldset.filter {
                    legend { "Filter" }
                    .categories {
                        @for (cname, cat) in FILTER_CATS {
                            .category {
                                h3 { @trs(lang, cname) }
                                @for (value, label) in *cat {
                                    label { input[type="checkbox", name="filter_kind", value=A(*value), checked=f.filter_kind.as_ref().map(|k|k.contains(value)).unwrap_or(true)]; @trs(lang, label) } br;
                                }
                            }
                        }
                    }
                }
                fieldset.sortby {
                    legend { "Sort" }
                    .categories {
                        @for (cname, cat) in SORT_CATS {
                            .category {
                                h3 { @trs(lang, cname) }
                                @for (value, label) in *cat {
                                    label { input[type="radio", name="sort_by", value=A(*value), checked=Some(value)==f.sort_by.as_ref()]; @trs(lang, label) } br;
                                }
                            }
                        }
                    }
                }
                fieldset.sortorder {
                    legend { "Sort Order" }
                    @use SortOrder::*;
                    @for (value, label) in [(Ascending, "filter_sort.order.asc"), (Descending, "filter_sort.order.desc")] {
                        label { input[type="radio", name="sort_order", value=A(value), checked=Some(value)==f.sort_order]; @trs(lang, label) } br;
                    }
                }
                input[type="submit", value="Apply"]; a[href="?"] { "Clear" }
            }
        }
    }
}

struct A<T>(pub T);
impl markup::Render for A<SortProperty> {
    fn render(&self, writer: &mut impl std::fmt::Write) -> std::fmt::Result {
        writer.write_str(self.0.to_str())
    }
}
impl markup::Render for A<SortOrder> {
    fn render(&self, writer: &mut impl std::fmt::Write) -> std::fmt::Result {
        writer.write_str(self.0.to_str())
    }
}
impl markup::Render for A<FilterProperty> {
    fn render(&self, writer: &mut impl std::fmt::Write) -> std::fmt::Result {
        writer.write_str(self.0.to_str())
    }
}
impl RenderAttributeValue for A<SortOrder> {}
impl RenderAttributeValue for A<FilterProperty> {}
impl RenderAttributeValue for A<SortProperty> {}
