// SPDX-FileCopyrightText: 2026 Ololduck <ololduck@vit.am> and contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later

//! Admin interface views using maud templates.

use maud::{Markup, html};

use crate::auth::AdminUser;
use crate::entities::{instance_blocks, reports, users};
use crate::views::components::{
    ActionButton, ActionMethod, ActionVariant, Complaint, FrogueUsername, TextField,
};
use crate::views::notes::Note;
use crate::views::{Page, ViewCtx};

/// A reported object: either a local note rendered inline or an external link.
pub enum ReportedObject {
    /// Local note: render inline using the existing note component.
    LocalNote(Box<Note>),
    /// External URL: render as a plain link.
    ExternalLink(String),
}

/// Convert an actor URL to @user@domain format for display.
/// Returns None if the URL cannot be parsed.
fn url_to_handle(url: &str) -> Option<String> {
    let parsed = url::Url::parse(url).ok()?;
    let domain = parsed.host_str()?;

    // Try to extract username from path
    // Common patterns: /users/username, /@username, or just /username
    let path = parsed.path().trim_start_matches('/');
    let username = if let Some(rest) = path.strip_prefix("users/") {
        rest.split('/').next()?
    } else if let Some(rest) = path.strip_prefix('@') {
        rest.split('/').next()?
    } else {
        path.split('/').next()?
    };

    if username.is_empty() {
        None
    } else {
        Some(format!("@{}@{}", username, domain))
    }
}

/// Admin home page
pub fn home(admin: &AdminUser, pending_reports: u64, error: Option<&str>) -> Page<Markup> {
    let ctx = ViewCtx::admin(admin.id, admin.name.clone(), pending_reports);

    Page {
        title: "Admin Dashboard".to_string(),
        ctx,
        extra_head: None,
        body: html! {
            h1 { "Admin Dashboard" }
            (Complaint(error))

            nav {
                ul {
                    li { a href="/admin/users" { "User Management" } }
                    li { a href="/admin/reports" { "Report Queue" } }
                    li { a href="/admin/federation" { "Federation Controls" } }
                }
            }
        },
    }
}

/// Users list page
pub fn users_list(
    admin: &AdminUser,
    users: &[users::Model],
    repo_counts: &std::collections::HashMap<i64, usize>,
    note_counts: &std::collections::HashMap<i64, usize>,
    pending_reports: u64,
    error: Option<&str>,
) -> Page<Markup> {
    let ctx = ViewCtx::admin(admin.id, admin.name.clone(), pending_reports);

    Page {
        title: "User Management".to_string(),
        ctx,
        extra_head: None,
        body: html! {
            h1 { "User Management" }
            (Complaint(error))

            table {
                thead {
                    tr {
                        th { "ID" }
                        th { "Name" }
                        th { "Email" }
                        th { "Repos" }
                        th { "Notes" }
                        th { "Created At" }
                        th { "Actions" }
                    }
                }
                tbody {
                    @for user in users {
                        tr {
                            td { (user.id) }
                            td { (FrogueUsername(&user.name)) }
                            td { (user.email) }
                            td { (repo_counts.get(&user.id).copied().unwrap_or(0)) }
                            td { (note_counts.get(&user.id).copied().unwrap_or(0)) }
                            td { (user.created_at.format("%Y-%m-%d %H:%M")) }
                            td {
                                @if user.id == 1 {
                                    span { "Admin (protected)" }
                                } @else {
                                    (ActionButton {
                                        action: format!("/admin/users/{}/delete", user.id),
                                        label: "Delete",
                                        variant: ActionVariant::Danger,
                                        hidden: &[],
                                        confirm: Some("This will permanently delete the user and all their data."),
                                        method: ActionMethod::Post,
                                    })
                                }
                            }
                        }
                    }
                }
            }
        },
    }
}

/// Reports list page
pub fn reports_list(
    admin: &AdminUser,
    reports: &[reports::Model],
    users: &[users::Model],
    remote_actors: &[crate::entities::ap_remote_actors::Model],
    current_filter: Option<&str>,
    pending_reports: u64,
    error: Option<&str>,
) -> Page<Markup> {
    let ctx = ViewCtx::admin(admin.id, admin.name.clone(), pending_reports);

    // Build user lookup for resolving local reporters/targets
    let user_by_id: std::collections::HashMap<i64, &users::Model> =
        users.iter().map(|u| (u.id, u)).collect();

    // Build remote actor lookup for resolving remote reporters/targets
    let remote_actor_by_id: std::collections::HashMap<
        i64,
        &crate::entities::ap_remote_actors::Model,
    > = remote_actors.iter().map(|a| (a.id, a)).collect();

    Page {
        title: "Report Queue".to_string(),
        ctx,
        extra_head: None,
        body: html! {
            h1 { "Report Queue" }
            (Complaint(error))

            // State filter form
            form method="get" action="/admin/reports" style="margin-bottom: 1em;" {
                label for="state" { "Filter by state: " }
                select name="state" id="state" {
                    option value="" selected[current_filter.is_none()] { "All" }
                    option value="open" selected[current_filter == Some("open")] { "Open" }
                    option value="resolved" selected[current_filter == Some("resolved")] { "Resolved" }
                    option value="dismissed" selected[current_filter == Some("dismissed")] { "Dismissed" }
                }
                button type="submit" { "Filter" }
            }

            @if reports.is_empty() {
                p { "No reports found." }
            } @else {
                table {
                    thead {
                        tr {
                            th { "UUID" }
                            th { "Reporter" }
                            th { "Target" }
                            th { "Reason" }
                            th { "Objects" }
                            th { "State" }
                            th { "Forwarded" }
                            th { "Inbound" }
                            th { "Created At" }
                            th { "Actions" }
                        }
                    }
                    tbody {
                        @for report in reports {
                            tr {
                                td { (report.uuid) }
                                td {
                                    @if let Some(user_id) = report.reporter_local_user_id {
                                        @if let Some(user) = user_by_id.get(&user_id) {
                                            (FrogueUsername(&user.name))
                                        } @else {
                                            "Unknown local user"
                                        }
                                    } @else if let Some(url) = &report.reporter_remote_actor_url {
                                        @if let Some(handle) = url_to_handle(url) {
                                            a href=(url) { (handle) }
                                        } @else {
                                            a href=(url) { (url) }
                                        }
                                        " "
                                        span class="remote-badge" { "remote" }
                                    }
                                }
                                td {
                                    @if let Some(user_id) = report.target_local_user_id {
                                        @if let Some(user) = user_by_id.get(&user_id) {
                                            (FrogueUsername(&user.name))
                                        } @else {
                                            "Unknown local user"
                                        }
                                    } @else if let Some(actor_id) = report.target_remote_actor_id {
                                        @if let Some(actor) = remote_actor_by_id.get(&actor_id) {
                                            @if let Some(handle) = url_to_handle(&actor.actor_url) {
                                                a href=(actor.actor_url) { (handle) }
                                            } @else {
                                                a href=(actor.actor_url) { (actor.actor_url) }
                                            }
                                        } @else {
                                            (format!("Remote actor #{}", actor_id))
                                        }
                                    } @else {
                                        "Unknown"
                                    }
                                }
                                td { (report.comment.as_deref().unwrap_or("No reason provided")) }
                                td {
                                    // Count objects in the JSON array
                                    @if let Ok(objects) = serde_json::from_str::<Vec<String>>(&report.object_urls) {
                                        (objects.len())
                                    } @else {
                                        "0"
                                    }
                                }
                                td { (report.state) }
                                td {
                                    @if report.forwarded != 0 {
                                        "✓"
                                    } @else {
                                        "—"
                                    }
                                }
                                td {
                                    @if report.inbound != 0 {
                                        "✓"
                                    } @else {
                                        "—"
                                    }
                                }
                                td { (report.created_at.format("%Y-%m-%d %H:%M")) }
                                td {
                                    a href=(format!("/admin/reports/{}", report.uuid)) { "View" }
                                    " "
                                    (ActionButton {
                                        action: format!("/admin/reports/{}/resolve", report.uuid),
                                        label: "Resolve",
                                        variant: ActionVariant::Solid,
                                        hidden: &[],
                                        confirm: None,
                                        method: ActionMethod::Post,
                                    })
                                    (ActionButton {
                                        action: format!("/admin/reports/{}/dismiss", report.uuid),
                                        label: "Dismiss",
                                        variant: ActionVariant::Quiet,
                                        hidden: &[],
                                        confirm: None,
                                        method: ActionMethod::Post,
                                    })
                                }
                            }
                        }
                    }
                }
            }
        },
    }
}

/// Report detail page
#[allow(clippy::too_many_arguments)]
pub fn report_detail(
    admin: &AdminUser,
    report: &reports::Model,
    reporter_user: Option<&users::Model>,
    reporter_remote_url: Option<&str>,
    target_user: Option<&users::Model>,
    target_remote: Option<&crate::entities::ap_remote_actors::Model>,
    reported_objects: &[ReportedObject],
    pending_reports: u64,
    error: Option<&str>,
) -> Page<Markup> {
    let ctx = ViewCtx::admin(admin.id, admin.name.clone(), pending_reports);

    Page {
        title: format!("Report {}", report.uuid),
        ctx,
        extra_head: None,
        body: html! {
            h1 { "Report Details" }
            (Complaint(error))

            p {
                a href="/admin/reports" { "← Back to Report Queue" }
            }

            section {
                h2 { "Report Information" }
                dl {
                    dt { "UUID" }
                    dd { code { (report.uuid) } }

                    dt { "State" }
                    dd { (report.state) }

                    dt { "Created At" }
                    dd { (report.created_at.format("%Y-%m-%d %H:%M:%S UTC")) }

                    dt { "Forwarded" }
                    dd { (report.forwarded) }

                    dt { "Inbound" }
                    dd { (report.inbound) }

                    @if let Some(comment) = &report.comment {
                        dt { "Comment" }
                        dd { (comment) }
                    }
                }
            }

            section {
                h2 { "Reporter" }
                @if let Some(user) = reporter_user {
                    dl {
                        dt { "Local User" }
                        dd {
                            a href=(format!("/@{}", user.name)) { (FrogueUsername(&user.name)) }
                        }
                    }
                } @else if let Some(url) = reporter_remote_url {
                    dl {
                        dt { "Remote Actor" }
                        dd {
                            a href=(url) { (url) }
                        }
                    }
                    div class="moderation-shortcuts" {
                        h3 { "Moderation Actions" }
                        form method="post" action="/admin/federation/block-remote-user" style="display:inline" {
                            input type="hidden" name="actor_url" value=(url);
                            input type="hidden" name="reason" value=(format!("Reported content: {}", report.uuid));
                            button type="submit" { "Block Remote User" }
                        }
                        " "
                        form method="post" action="/admin/federation/block-domain" style="display:inline" {
                            @if let Some(domain) = url.split("://").nth(1).and_then(|s| s.split('/').next()) {
                                input type="hidden" name="domain" value=(domain);
                                input type="hidden" name="reason" value=(format!("Reporter domain for report: {}", report.uuid));
                                button type="submit" { "Defederate Domain" }
                            }
                        }
                    }
                } @else {
                    p { "Unknown reporter" }
                }
            }

            section {
                h2 { "Target" }
                @if let Some(user) = target_user {
                    dl {
                        dt { "Local User" }
                        dd {
                            a href=(format!("/@{}", user.name)) { (FrogueUsername(&user.name)) }
                        }
                    }
                } @else if let Some(actor) = target_remote {
                    dl {
                        dt { "Remote Actor" }
                        dd {
                            a href=(actor.actor_url) { (actor.actor_url) }
                        }
                    }
                    div class="moderation-shortcuts" {
                        h3 { "Moderation Actions" }
                        form method="post" action="/admin/federation/block-remote-user" style="display:inline" {
                            input type="hidden" name="actor_url" value=(actor.actor_url);
                            input type="hidden" name="reason" value=(format!("Reported content: {}", report.uuid));
                            button type="submit" { "Block Remote User" }
                        }
                        " "
                        form method="post" action="/admin/federation/block-domain" style="display:inline" {
                            @if let Some(domain) = actor.actor_url.split("://").nth(1).and_then(|s| s.split('/').next()) {
                                input type="hidden" name="domain" value=(domain);
                                input type="hidden" name="reason" value=(format!("Target domain for report: {}", report.uuid));
                                button type="submit" { "Defederate Domain" }
                            }
                        }
                    }
                } @else {
                    p { "Unknown target" }
                }
            }

            @if !reported_objects.is_empty() {
                section {
                    h2 { "Reported Objects" }
                    @for obj in reported_objects {
                        @match obj {
                            ReportedObject::LocalNote(note) => {
                                div class="reported-object reported-object--local-note" {
                                    (&**note)
                                }
                            }
                            ReportedObject::ExternalLink(url) => {
                                div class="reported-object reported-object--external" {
                                    a href=(url) target="_blank" rel="noopener noreferrer" { (url) }
                                }
                            }
                        }
                    }
                }
            }

            section {
                h2 { "Actions" }
                div class="report-actions" {
                    @if report.state == "open" {
                        (ActionButton {
                            action: format!("/admin/reports/{}/resolve", report.uuid),
                            label: "Resolve",
                            variant: ActionVariant::Solid,
                            hidden: &[],
                            confirm: None,
                            method: ActionMethod::Post,
                        })
                        (ActionButton {
                            action: format!("/admin/reports/{}/dismiss", report.uuid),
                            label: "Dismiss",
                            variant: ActionVariant::Quiet,
                            hidden: &[],
                            confirm: None,
                            method: ActionMethod::Post,
                        })
                    } @else {
                        p { (format!("Report is {}", report.state)) }
                    }
                }
            }
        },
    }
}

/// Federation controls page
pub fn federation(
    admin: &AdminUser,
    blocks: &[instance_blocks::Model],
    admin_blocks: &[crate::entities::admin_remote_blocks::Model],
    remote_actors: &[crate::entities::ap_remote_actors::Model],
    users: &[crate::entities::users::Model],
    pending_reports: u64,
    error: Option<&str>,
) -> Page<Markup> {
    let ctx = ViewCtx::admin(admin.id, admin.name.clone(), pending_reports);

    // Build lookup for remote actor URLs
    let remote_actor_by_id: std::collections::HashMap<
        i64,
        &crate::entities::ap_remote_actors::Model,
    > = remote_actors.iter().map(|a| (a.id, a)).collect();

    // Build lookup for admin user names (blocked_by)
    let user_by_id: std::collections::HashMap<i64, &crate::entities::users::Model> =
        users.iter().map(|u| (u.id, u)).collect();

    Page {
        title: "Federation Controls".to_string(),
        ctx,
        extra_head: None,
        body: html! {
            h1 { "Federation Controls" }
            (Complaint(error))

            section {
                h2 { "Block Domain" }
                form method="post" action="/admin/federation/block-domain" {
                    (TextField {
                        label: Some("Domain"),
                        name: "domain",
                        input_type: "text",
                        value: None,
                        required: true,
                        maxlength: 253,
                    })

                    (TextField {
                        label: Some("Reason"),
                        name: "reason",
                        input_type: "text",
                        value: None,
                        required: false,
                        maxlength: 500,
                    })

                    (ActionButton {
                        action: "/admin/federation/block-domain".to_string(),
                        label: "Block Domain",
                        variant: ActionVariant::Danger,
                        hidden: &[],
                        confirm: None,
                        method: ActionMethod::Post,
                    })
                }
            }
            /*
            section {
                h2 { "Unblock Domain" }
                form method="post" action="/admin/federation/unblock-domain" {
                    (TextField {
                        label: Some("Domain"),
                        name: "domain",
                        input_type: "text",
                        value: None,
                        required: true,
                        maxlength: 253,
                    })

                    (ActionButton {
                        action: "/admin/federation/unblock-domain".to_string(),
                        label: "Unblock Domain",
                        variant: ActionVariant::Solid,
                        hidden: &[],
                        confirm: None,
                        method: ActionMethod::Post,
                    })
                }
            }
            */
            section {
                h2 { "Block Remote User" }
                form method="post" action="/admin/federation/block-remote-user" {
                    (TextField {
                        label: Some("Actor URL"),
                        name: "actor_url",
                        input_type: "url",
                        value: None,
                        required: true,
                        maxlength: 2000,
                    })

                    (TextField {
                        label: Some("Reason"),
                        name: "reason",
                        input_type: "text",
                        value: None,
                        required: false,
                        maxlength: 500,
                    })

                    (ActionButton {
                        action: "/admin/federation/block-remote-user".to_string(),
                        label: "Block Remote User",
                        variant: ActionVariant::Danger,
                        hidden: &[],
                        confirm: Some("This will remove follow relationships and deliver a Block activity."),
                        method: ActionMethod::Post,
                    })
                }
            }
            /*
            section {
                h2 { "Unblock Remote User" }
                form method="post" action="/admin/federation/unblock-remote-user" {
                    (TextField {
                        label: Some("Remote Actor ID"),
                        name: "remote_actor_id",
                        input_type: "number",
                        value: None,
                        required: true,
                        maxlength: 20,
                    })

                    (ActionButton {
                        action: "/admin/federation/unblock-remote-user".to_string(),
                        label: "Unblock Remote User",
                        variant: ActionVariant::Solid,
                        hidden: &[],
                        confirm: None,
                        method: ActionMethod::Post,
                    })
                }
            }
            */
            @if !blocks.is_empty() {
                section {
                    h2 { "Blocked Domains" }
                    table {
                        thead {
                            tr {
                                th { "Domain" }
                                th { "Reason" }
                                th { "Blocked By" }
                                th { "Blocked At" }
                                th { "Actions" }
                            }
                        }
                        tbody {
                            @for block in blocks {
                                tr {
                                    td { (block.domain) }
                                    td { (block.reason.as_deref().unwrap_or("-")) }
                                    td {
                                        @if let Some(user) = user_by_id.get(&block.blocked_by) {
                                            (user.name)
                                        } @else {
                                            "Unknown"
                                        }
                                    }
                                    td { (block.created_at.format("%Y-%m-%d %H:%M")) }
                                    td {
                                        form method="post" action="/admin/federation/unblock-domain" {
                                            input type="hidden" name="domain" value=(block.domain);
                                            (ActionButton {
                                                action: "/admin/federation/unblock-domain".to_string(),
                                                label: "Unblock",
                                                variant: ActionVariant::Quiet,
                                                hidden: &[("domain", &block.domain)],
                                                confirm: None,
                                                method: ActionMethod::Post,
                                            })
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            @if !admin_blocks.is_empty() {
                section {
                    h2 { "Blocked Remote Users" }
                    table {
                        thead {
                            tr {
                                th { "Actor URL" }
                                th { "Name" }
                                th { "Reason" }
                                th { "Blocked At" }
                                th { "Actions" }
                            }
                        }
                        tbody {
                            @for block in admin_blocks {
                                tr {
                                    td {
                                        @if let Some(actor) = remote_actor_by_id.get(&block.remote_actor_id) {
                                            a href=(actor.actor_url) { (actor.actor_url) }
                                        } @else {
                                            (format!("Remote actor #{}", block.remote_actor_id))
                                        }
                                    }
                                    td {
                                        @if let Some(actor) = remote_actor_by_id.get(&block.remote_actor_id) {
                                            @if let Some(name) = &actor.name {
                                                (name)
                                            } @else if let Some(username) = &actor.preferred_username {
                                                (username)
                                            } @else {
                                                "-"
                                            }
                                        } @else {
                                            "-"
                                        }
                                    }
                                    td { (block.reason.as_deref().unwrap_or("-")) }
                                    td { (block.created_at.format("%Y-%m-%d %H:%M")) }
                                    td {
                                        form method="post" action="/admin/federation/unblock-remote-user" {
                                            input type="hidden" name="remote_actor_id" value=(block.remote_actor_id);
                                            (ActionButton {
                                                action: "/admin/federation/unblock-remote-user".to_string(),
                                                label: "Unblock",
                                                variant: ActionVariant::Quiet,
                                                hidden: &[("remote_actor_id", &block.remote_actor_id.to_string())],
                                                confirm: None,
                                                method: ActionMethod::Post,
                                            })
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
    }
}
