use gotcha_gitea::{models, notifications};

use super::{ActivityTargetKind, NotificationRow, compact_date};

pub fn notification_rows(
    server_id: &str,
    notifications: Vec<models::NotificationThread>,
) -> Vec<NotificationRow> {
    notifications
        .into_iter()
        .filter_map(|notification| notification_row(server_id, notification))
        .collect()
}

fn notification_row(
    server_id: &str,
    notification: models::NotificationThread,
) -> Option<NotificationRow> {
    let id = notification.id?;
    let title = notification
        .subject
        .as_deref()
        .and_then(|subject| subject.title.clone())
        .filter(|title| !title.is_empty())
        .unwrap_or_else(|| "Server notification".into());
    let kind = notification
        .subject
        .as_deref()
        .and_then(|subject| subject.r#type.as_deref())
        .unwrap_or("Update");
    let full_name = notification
        .repository
        .as_deref()
        .and_then(|repository| repository.full_name.clone())
        .or_else(|| {
            let repository = notification.repository.as_deref()?;
            Some(format!(
                "{}/{}",
                repository.owner.as_deref()?.login.as_deref()?,
                repository.name.as_deref()?
            ))
        })
        .unwrap_or_else(|| "Server".into());
    let (target, owner, repository, number, sha) = match notifications::target(&notification) {
        notifications::NotificationTarget::None => (
            ActivityTargetKind::None,
            String::new(),
            String::new(),
            0,
            String::new(),
        ),
        notifications::NotificationTarget::Repository { owner, repository } => (
            ActivityTargetKind::Repository,
            owner,
            repository,
            0,
            String::new(),
        ),
        notifications::NotificationTarget::Issue {
            owner,
            repository,
            number,
        } => (
            ActivityTargetKind::Issue,
            owner,
            repository,
            number,
            String::new(),
        ),
        notifications::NotificationTarget::Pull {
            owner,
            repository,
            number,
        } => (
            ActivityTargetKind::PullRequest,
            owner,
            repository,
            number,
            String::new(),
        ),
        notifications::NotificationTarget::Commit {
            owner,
            repository,
            sha,
        } => (ActivityTargetKind::Commit, owner, repository, 0, sha),
    };
    Some(NotificationRow {
        id,
        server_id: server_id.into(),
        title,
        detail: format!("{kind} · {full_name}"),
        meta: compact_date(notification.updated_at.as_deref()),
        unread: notification.unread.unwrap_or_default(),
        target,
        owner,
        repository,
        number,
        sha,
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn presents_targetable_notification_without_exposing_api_models() {
        let rows = notification_rows(
            "work",
            vec![models::NotificationThread {
                id: Some(9),
                unread: Some(true),
                updated_at: Some("2026-08-15T10:00:00Z".into()),
                repository: Some(Box::new(models::Repository {
                    full_name: Some("octo/demo".into()),
                    name: Some("demo".into()),
                    owner: Some(Box::new(models::User {
                        login: Some("octo".into()),
                        ..Default::default()
                    })),
                    ..Default::default()
                })),
                subject: Some(Box::new(models::NotificationSubject {
                    title: Some("Fix the bug".into()),
                    r#type: Some("Issue".into()),
                    url: Some("https://example/api/v1/repos/octo/demo/issues/42".into()),
                    ..Default::default()
                })),
                ..Default::default()
            }],
        );

        assert_eq!(rows.len(), 1);
        assert_eq!(rows[0].id, 9);
        assert_eq!(rows[0].server_id, "work");
        assert_eq!(rows[0].title, "Fix the bug");
        assert_eq!(rows[0].detail, "Issue · octo/demo");
        assert!(rows[0].unread);
        assert_eq!(rows[0].target, ActivityTargetKind::Issue);
        assert_eq!(rows[0].number, 42);
    }
}
