//! Table-formatted output for verification reports.

use crate::verify::{AuditVerdict, VerifyReport};

/// Format a verification report as a terminal table.
pub fn format_verify_table(
    report: &VerifyReport,
    project_name: &str,
    show_unclaimed: bool,
) -> String {
    let mut out = String::new();

    out.push_str(&format!("Aphoria Verify - {project_name}\n"));
    out.push_str(&"=".repeat(60));
    out.push('\n');
    out.push('\n');

    let mut has_output = false;

    for result in &report.results {
        if result.verdict == AuditVerdict::Unclaimed && !show_unclaimed {
            continue;
        }

        has_output = true;
        let label = match result.verdict {
            AuditVerdict::Pass => "  PASS    ",
            AuditVerdict::Conflict => "  CONFLICT",
            AuditVerdict::Missing => "  MISSING ",
            AuditVerdict::Unclaimed => "  UNCLAIMD",
        };

        // Claim summary line
        let (claim_id, value_display) = if let Some(ref claim) = result.claim {
            let display = match claim.comparison {
                crate::types::ComparisonMode::Absent => {
                    format!("{} (absent)", claim.concept_path)
                }
                crate::types::ComparisonMode::Present => {
                    format!("{} (present)", claim.concept_path)
                }
                _ => {
                    format!("{}/{} = {}", claim.concept_path, claim.predicate, claim.value)
                }
            };
            (claim.id.as_str(), display)
        } else {
            // Unclaimed observation — no backing claim
            let display = if let Some(obs) = result.matching_observations.first() {
                format!("{} ({})", obs.concept_path, obs.predicate)
            } else {
                "(unclaimed)".to_string()
            };
            ("(unclaimed)", display)
        };

        out.push_str(&format!("{label} {claim_id} | {value_display}\n"));

        // Detail lines
        match result.verdict {
            AuditVerdict::Pass => {
                if let Some(obs) = result.matching_observations.first() {
                    out.push_str(&format!(
                        "           Matched: {}:{} (confidence {:.1})\n",
                        obs.file, obs.line, obs.confidence
                    ));
                }
            }
            AuditVerdict::Conflict => {
                for obs in &result.matching_observations {
                    out.push_str(&format!(
                        "           Found: {}:{} ({} = {:?})\n",
                        obs.file, obs.line, obs.predicate, obs.value
                    ));
                }
                if let Some(ref claim) = result.claim {
                    if !claim.consequence.is_empty() {
                        out.push_str(&format!("           Consequence: {}\n", claim.consequence));
                    }
                }
            }
            AuditVerdict::Missing => {
                out.push_str("           No matching observation found\n");
            }
            AuditVerdict::Unclaimed => {
                for obs in &result.matching_observations {
                    out.push_str(&format!("           At: {}:{}\n", obs.file, obs.line));
                }
            }
        }
        out.push('\n');
    }

    if !has_output {
        out.push_str("  No results to display.\n\n");
    }

    out.push_str(&"=".repeat(60));
    out.push('\n');

    let s = &report.summary;
    out.push_str(&format!(
        "Claims: {} total | {} pass | {} conflict | {} missing",
        s.total_claims, s.pass, s.conflict, s.missing
    ));
    if show_unclaimed {
        out.push_str(&format!(" | {} unclaimed", s.unclaimed));
    }
    out.push('\n');

    out
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::verify::{VerifyReport, VerifySummary};

    #[test]
    fn test_empty_report() {
        let report = VerifyReport { results: vec![], summary: VerifySummary::default() };
        let output = format_verify_table(&report, "test-project", false);
        assert!(output.contains("Aphoria Verify - test-project"));
        assert!(output.contains("0 total"));
    }
}
