//! Module: sns::report::text::proposals::list
//!
//! Responsibility: render SNS proposal list reports as text.
//! Does not own: proposal fetching, cache filtering, report construction, or JSON output.
//! Boundary: formats live or cache-backed proposal rows for humans.

use super::{
    SNS_PROPOSAL_DETAIL_TEXT_LIMIT,
    detail::{proposal_detail_lines, proposal_title_for_list},
};
use crate::{
    sns::report::{
        SnsProposalsReport,
        text::common::{optional_u64_text, push_report_provenance_lines, yes_no},
    },
    table::{ColumnAlign, render_table},
};

#[must_use]
pub fn sns_proposals_report_text(report: &SnsProposalsReport) -> String {
    let mut lines = vec![
        format!("network: {}", report.network),
        format!("sns_id: {}", report.id),
        format!("name: {}", report.name),
        format!("root_canister_id: {}", report.root_canister_id),
        format!("governance_canister_id: {}", report.governance_canister_id),
        format!("requested_limit: {}", report.requested_limit),
        format!(
            "before_proposal_id: {}",
            optional_u64_text(report.before_proposal_id)
        ),
        format!("status_filter: {}", report.status_filter),
        format!("topic_filter: {}", report.topic_filter),
        format!("eligibility_filter: {}", report.eligibility_filter),
        format!(
            "proposer_filter: {}",
            report.proposer_filter.as_deref().unwrap_or("-")
        ),
        format!(
            "query_filter: {}",
            report.query_filter.as_deref().unwrap_or("-")
        ),
        format!("sort: {}", report.sort),
        format!("sort_direction: {}", report.sort_direction),
        format!("verbose: {}", yes_no(report.verbose)),
    ];
    push_report_provenance_lines(
        &mut lines,
        &report.data_source,
        report.cache_path.as_deref(),
        report.cache_complete,
    );
    lines.extend([
        format!("proposal_count: {}", report.proposal_count),
        format!("sns_wasm_canister_id: {}", report.sns_wasm_canister_id),
        format!("fetched_at: {}", report.fetched_at),
        format!("source_endpoint: {}", report.source_endpoint),
    ]);
    if !report.proposals.is_empty() {
        lines.push(String::new());
        lines.push(render_table(
            &["ID", "ACTION", "DECISION", "CREATED_AT", "TITLE"],
            &report
                .proposals
                .iter()
                .map(|proposal| {
                    [
                        optional_u64_text(proposal.proposal_id),
                        proposal.action.clone(),
                        proposal.decision_state.clone(),
                        proposal.created_at.clone(),
                        proposal_title_for_list(proposal, report.verbose),
                    ]
                })
                .collect::<Vec<_>>(),
            &[
                ColumnAlign::Right,
                ColumnAlign::Left,
                ColumnAlign::Left,
                ColumnAlign::Left,
                ColumnAlign::Left,
            ],
        ));
    }
    if report.verbose && !report.proposals.is_empty() {
        lines.push(String::new());
        lines.push("proposal_details:".to_string());
        for proposal in &report.proposals {
            lines.extend(proposal_detail_lines(
                proposal,
                Some(SNS_PROPOSAL_DETAIL_TEXT_LIMIT),
            ));
        }
    }
    lines.join("\n")
}
