"""Render Scout findings for CLI output."""

from __future__ import annotations

from typing import Any, Iterable, List

from .models import ScoutFinding, ScoutScanResult


def _truncate(value: str, max_len: int = 64) -> str:
    if len(value) <= max_len:
        return value
    return value[: max_len - 3] + "..."


def _format_value(value: Any) -> str:
    if value is None:
        return ""
    text = str(value)
    return _truncate(text)


def _format_table(headers: List[str], rows: List[List[str]]) -> str:
    widths = [len(h) for h in headers]
    for row in rows:
        for idx, cell in enumerate(row):
            widths[idx] = max(widths[idx], len(cell))
    sep = "+" + "+".join("-" * (w + 2) for w in widths) + "+"
    header_line = "|" + "|".join(f" {headers[i].ljust(widths[i])} " for i in range(len(headers))) + "|"
    lines = [sep, header_line, sep]
    for row in rows:
        line = "|" + "|".join(f" {row[i].ljust(widths[i])} " for i in range(len(headers))) + "|"
        lines.append(line)
    lines.append(sep)
    return "\n".join(lines)


def _summarize_fields(fields: dict[str, Any], max_items: int = 3) -> str:
    if not fields:
        return ""
    items: List[str] = []
    for idx, (key, value) in enumerate(fields.items()):
        if idx >= max_items:
            break
        items.append(f"{key}={_format_value(value)}")
    return "; ".join(items)


def render_finding_table(finding: ScoutFinding, include_fields: bool = True) -> str:
    title = finding.display_name or finding.scout_name
    lines: List[str] = []
    lines.append(f"Scout: {title} ({finding.scout_name})")
    lines.append(
        f"Status: {finding.status} | Total scanned: {finding.total_records_scanned} | "
        f"Findings: {finding.findings_count} | Duration: {finding.duration_ms} ms"
    )
    if finding.category or finding.severity:
        lines.append(f"Category: {finding.category or ''} | Severity: {finding.severity or ''}")
    if finding.status_detail:
        lines.append(f"Detail: {finding.status_detail}")
    if finding.warnings:
        lines.append("Warnings: " + "; ".join(finding.warnings))

    if not finding.evidence:
        return "\n".join(lines)

    headers = ["Record Id", "Reason Code", "Reason", "SObject"]
    if include_fields:
        headers.append("Fields")

    rows: List[List[str]] = []
    for row in finding.evidence:
        row_values = [
            _format_value(row.record_id),
            _format_value(row.reason_code),
            _format_value(row.reason),
            _format_value(row.sobject),
        ]
        if include_fields:
            row_values.append(_summarize_fields(row.fields))
        rows.append(row_values)

    lines.append("")
    lines.append(_format_table(headers, rows))
    return "\n".join(lines)


def render_scan_summary(scan_result: ScoutScanResult) -> str:
    headers = ["Scout", "Status", "Findings", "Total", "Duration (ms)"]
    rows: List[List[str]] = []
    for finding in scan_result.findings:
        title = finding.display_name or finding.scout_name
        rows.append(
            [
                _format_value(title),
                _format_value(finding.status),
                _format_value(str(finding.findings_count)),
                _format_value(str(finding.total_records_scanned)),
                _format_value(str(finding.duration_ms)),
            ]
        )
    summary = _format_table(headers, rows)
    meta = (
        f"Scout scan {scan_result.run_id} | Started: {scan_result.started_at} | "
        f"Ended: {scan_result.ended_at} | Duration: {scan_result.total_duration_ms} ms"
    )
    return "\n".join([meta, summary])


def render_scan_with_findings(scan_result: ScoutScanResult, include_fields: bool = True) -> str:
    parts = [render_scan_summary(scan_result)]
    for finding in scan_result.findings:
        parts.append("")
        parts.append(render_finding_table(finding, include_fields=include_fields))
    return "\n".join(parts)


__all__ = ["render_finding_table", "render_scan_summary", "render_scan_with_findings"]
