from __future__ import annotations
import csv
import json
import os
from dataclasses import asdict
from typing import List, Optional
from datetime import datetime
from zoneinfo import ZoneInfo
from models import Result

def prepare_output_path(base_dir: str = "reports") -> str:
    """
    Create a timestamped output directory
    """
    ts = datetime.now(ZoneInfo("Europe/Rome")).strftime("%Y-%m-%d_%H-%M-%S")
    out_dir = os.path.join(base_dir, ts)
    os.makedirs(out_dir, exist_ok=True)
    return out_dir


def print_table(results: List[Result]) -> None:
    headers = ["Input", "eTLD+1", "Score", "Level", "Reasons"]
    rows = []
    for r in results:
        rows.append([
            r.domain_input,
            r.etld_plus_one,
            str(r.risk_score),
            r.risk_level,
            ",".join(r.reasons[:6]) + ("..." if len(r.reasons) > 6 else "")
        ])
    widths = [max(len(h), max((len(row[i]) for row in rows), default=0)) for i, h in enumerate(headers)]
    fmt = " | ".join("{:<" + str(w) + "}" for w in widths)
    sep = "-+-".join("-" * w for w in widths)
    print(fmt.format(*headers))
    print(sep)
    for row in rows:
        print(fmt.format(*row))


def write_json(results: List[Result], out_path: Optional[str]) -> None:
    data = [asdict(r) for r in results]
    s = json.dumps(data, indent=2, ensure_ascii=False)
    if out_path:
        with open(out_path, "w", encoding="utf-8") as f:
            f.write(s)
    else:
        print(s)


def write_csv(results: List[Result], out_path: Optional[str]) -> None:
    fieldnames = [
        "domain_input", "etld_plus_one", "risk_score", "risk_level",
        "reasons",
        "idn", "mixed_scripts", "suspicious_tokens", "brand_in_subdomain",
        "mx_present",
        "dmarc_present", "dmarc_policy", "dmarc_pct", "dmarc_rua_present", "dmarc_ambiguous",
        "spf_present", "spf_multiple", "spf_all_qualifier", "spf_weak_all",
        "dkim_probed", "dkim_found_selectors",
        "timestamp_utc"
    ]

    out_rows = []
    for r in results:
        out_rows.append({
            "domain_input": r.domain_input,
            "etld_plus_one": r.etld_plus_one,
            "risk_score": r.risk_score,
            "risk_level": r.risk_level,
            "reasons": ";".join(r.reasons),
            "idn": r.syntax.idn,
            "mixed_scripts": r.syntax.mixed_scripts,
            "suspicious_tokens": ",".join(r.syntax.suspicious_tokens),
            "brand_in_subdomain": ",".join(r.syntax.brand_in_subdomain),
            "mx_present": r.mx.present,
            "dmarc_present": r.dmarc.present,
            "dmarc_policy": r.dmarc.policy,
            "dmarc_pct": r.dmarc.pct,
            "dmarc_rua_present": r.dmarc.rua_present,
            "dmarc_ambiguous": r.dmarc.ambiguous,
            "spf_present": r.spf.present,
            "spf_multiple": r.spf.multiple,
            "spf_all_qualifier": r.spf.all_qualifier,
            "spf_weak_all": r.spf.weak_all,
            "dkim_probed": r.dkim.probed,
            "dkim_found_selectors": ",".join(r.dkim.found_selectors),
            "timestamp_utc": r.timestamp_utc,
        })

    if out_path:
        f = open(out_path, "w", newline="", encoding="utf-8")
        close = True
    else:
        import sys
        f = sys.stdout
        close = False
    try:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        for row in out_rows:
            writer.writerow(row)
    finally:
        if close:
            f.close()
