use maud::{Markup, PreEscaped, Render, html};
use tracing::instrument;

use super::Page;
use super::components::Pagination;
use crate::activitypub::feed::FeedEntry;

pub const FEED_PAGE_SIZE: usize = 20;

/// The body of the index page: when a user is logged in and federation is
/// enabled, show their home feed. Otherwise show an empty page.
pub(super) struct Index {
    pub entries: Vec<FeedEntry>,
    pub public_url: String,
    pub viewer_username: Option<String>,
    pub page: u64,
}

impl Render for Index {
    fn render(&self) -> Markup {
        if self.entries.is_empty() {
            // Empty feed - show a message or empty page
            if self.viewer_username.is_some() {
                html! {
                    p { "Your feed is empty. Follow some remote users or post a note!" }
                }
            } else {
                html! {}
            }
        } else {
            html! {
                div class="feed" {
                    @for entry in &self.entries {
                        (render_feed_entry(entry, &self.public_url, &self.viewer_username))
                    }
                }
                (Pagination {
                    current_page: self.page,
                    has_next: self.entries.len() == FEED_PAGE_SIZE,
                    base_url: "/".to_string(),
                })
            }
        }
    }
}

/// Render a single feed entry.
fn render_feed_entry(
    entry: &FeedEntry,
    public_url: &str,
    viewer_username: &Option<String>,
) -> Markup {
    let author_handle = entry.author_handle();
    let content = entry.content();
    let permalink = match entry {
        FeedEntry::Local {
            uuid,
            author_username,
            ..
        } => format!("{public_url}/~{author_username}/notes/{uuid}"),
        FeedEntry::Remote { object_url, .. } => object_url.clone(),
    };

    let timestamp = entry.timestamp();
    let time_str = timestamp.format("%Y-%m-%d %H:%M UTC").to_string();

    let (reacted, boosted, remote_note_id) = match entry {
        FeedEntry::Local { reacted, .. } => (*reacted, false, None),
        FeedEntry::Remote {
            remote_note_id,
            reacted,
            boosted,
            ..
        } => (*reacted, *boosted, Some(*remote_note_id)),
    };

    html! {
        article class="feed-entry" {
            header class="feed-entry-header" {
                strong class="feed-entry-author" { (author_handle) }
                time datetime=(timestamp.to_rfc3339()) { (time_str) }
            }
            div class="feed-entry-content" {
                (PreEscaped(content))
            }
            footer class="feed-entry-footer" {
                a href=(permalink) { "permalink" }
                @if viewer_username.is_some() {
                    @if let Some(note_id) = remote_note_id {
                        @if reacted {
                            form method="post" action=(format!("/remote-notes/{}/unreact", note_id)) {
                                button type="submit" class="react-button reacted" { "❤️ Unreact" }
                            }
                        } @else {
                            form method="post" action=(format!("/remote-notes/{}/react", note_id)) {
                                button type="submit" class="react-button" { "❤️ React" }
                            }
                        }
                        @if boosted {
                            form method="post" action=(format!("/remote-notes/{}/unannounce", note_id)) {
                                button type="submit" class="react-button reacted" { "🔁 Unboost" }
                            }
                        } @else {
                            form method="post" action=(format!("/remote-notes/{}/announce", note_id)) {
                                button type="submit" class="react-button" { "🔁 Boost" }
                            }
                        }
                    }
                }
            }
        }
    }
}

/// The index page, as seen by `viewer` - nobody, when it is `None`.
/// When logged in and federation is enabled, shows the home feed.
#[instrument(skip(entries))]
pub fn index(
    viewer: Option<&str>,
    entries: Vec<FeedEntry>,
    public_url: &str,
    page: u64,
) -> HttpResponse {
    let viewer_username = viewer.map(str::to_string);
    Page {
        title: "Home - Frogue".to_string(),
        viewer: viewer_username.clone(),
        extra_head: None,
        body: Index {
            entries,
            public_url: public_url.to_string(),
            viewer_username,
            page,
        },
    }
    .into_response()
}

use actix_web::HttpResponse;
