"""
Pheser — Exporter
Export scan results to JSON, CSV, or a plain-text report.
"""

from __future__ import annotations
import csv
import json
import os
from typing import Any

from .utils import timestamp


def export_report(
    scan_results: dict[str, Any],
    output_file: str,
    *,
    fmt: str = "json",
    verbose: bool = True,
) -> str | None:
    """
    Export scan results to a file.

    Parameters
    ----------
    scan_results : Dict returned by scanner.scan(..., raw=True).
    output_file  : Destination file path.
    fmt          : "json" | "csv" | "txt"
    verbose      : Print confirmation.

    Returns
    -------
    Output file path on success, None on failure.
    """
    fmt = fmt.lower()
    if fmt not in ("json", "csv", "txt"):
        print(f"[pheser]  Unknown format: {fmt}. Use json, csv, or txt.")
        return None

    os.makedirs(os.path.dirname(os.path.abspath(output_file)), exist_ok=True)

    try:
        if fmt == "json":
            _export_json(scan_results, output_file)
        elif fmt == "csv":
            _export_csv(scan_results, output_file)
        elif fmt == "txt":
            _export_txt(scan_results, output_file)
    except Exception as e:
        print(f"[pheser]  Export failed: {e}")
        return None

    if verbose:
        print(f"[pheser]  Report exported ({fmt.upper()}) → {output_file}")

    return output_file


# ── Format writers ─────────────────────────────────────────────────────────────

def _export_json(results: dict, path: str):
    payload = {
        "generated": timestamp(),
        "source": results.get("file"),
        "image": {
            "format": results.get("format"),
            "mode": results.get("mode"),
            "size": results.get("size"),
            "file_size": results.get("file_size"),
            "sha256": results.get("sha256"),
        },
        "privacy": {
            "risk_score": results.get("risk_score"),
            "risk_label": results.get("risk_label"),
            "sensitive_tags": results.get("sensitive_tags"),
        },
        "gps": results.get("gps"),
        "exif": results.get("exif"),
    }
    with open(path, "w", encoding="utf-8") as f:
        json.dump(payload, f, indent=2, default=str)


def _export_csv(results: dict, path: str):
    rows: list[dict] = []
    for ifd, tags in (results.get("exif") or {}).items():
        for name, value in tags.items():
            rows.append({
                "file": results.get("file"),
                "ifd": ifd,
                "tag": name,
                "value": str(value),
                "sensitive": name in (results.get("sensitive_tags") or []),
            })

    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=["file", "ifd", "tag", "value", "sensitive"])
        writer.writeheader()
        writer.writerows(rows)


def _export_txt(results: dict, path: str):
    lines: list[str] = []
    w = lines.append

    w("=" * 60)
    w("  Pheser — METADATA REPORT")
    w(f"  Generated : {timestamp()}")
    w("=" * 60)
    w(f"  File      : {results.get('file')}")
    w(f"  Format    : {results.get('format')}  |  {results.get('file_size')}")
    sz = results.get("size")
    if sz:
        w(f"  Pixels    : {sz[0]} × {sz[1]}")
    w(f"  SHA256    : {results.get('sha256') or 'n/a'}")
    w("")
    w(f"  Risk      : {results.get('risk_label')}  ({results.get('risk_score')}/100)")
    sensitive = results.get("sensitive_tags") or []
    if sensitive:
        w(f"  Sensitive : {', '.join(sorted(set(sensitive)))}")
    w("")

    for ifd, tags in (results.get("exif") or {}).items():
        if not tags:
            continue
        w(f"  [{ifd}]")
        for name, val in tags.items():
            w(f"    {name:<30} {val}")
        w("")

    gps = results.get("gps")
    if gps:
        w("  GPS LOCATION")
        w(f"    Latitude  : {gps['latitude']}")
        w(f"    Longitude : {gps['longitude']}")
        w(f"    Maps      : {gps['maps_url']}")
        w("")

    w("=" * 60)

    with open(path, "w", encoding="utf-8") as f:
        f.write("\n".join(lines))