from __future__ import annotations

import json
from pathlib import Path
from typing import Optional

from auditwalk.cli.dispatch import Invocation
from auditwalk.core.store import latest_run_path, read_json, write_run_json
from auditwalk.modules.preflight import run_preflight


def _base_dir_from_opts(opts) -> Optional[Path]:
    out = opts.get("out")
    if not out:
        return None
    return Path(out)


def _print_preflight_text(payload: dict) -> None:
    prls = payload.get("prls", {})
    print("AuditWalk Preflight")
    print(f"  Run ID:   {payload.get('run_id')}")
    print(f"  Time:     {payload.get('created_at')}")
    print(f"  Host:     {payload.get('host', {}).get('hostname')}")
    print(f"  PRLS:     {prls.get('status')} (score={prls.get('score')})")
    issues = prls.get("issues") or []
    if issues:
        print("  Issues:")
        for issue in issues:
            print(f"    - {issue}")


def preflight_run(inv: Invocation) -> int:
    fmt = (inv.opts.get("format") or "text").lower()
    base_dir = _base_dir_from_opts(inv.opts)

    result = run_preflight()
    payload = result.to_dict()
    stored_path = write_run_json(result.run_id, payload, base=base_dir)

    if fmt == "json":
        print(json.dumps(payload, indent=2, sort_keys=True))
    else:
        _print_preflight_text(payload)
        print(f"  Stored:   {stored_path}")
    return 0


def preflight_show(inv: Invocation) -> int:
    fmt = (inv.opts.get("format") or "text").lower()
    base_dir = _base_dir_from_opts(inv.opts)
    path = latest_run_path(base=base_dir)
    if not path:
        print("No preflight runs found.")
        return 1

    payload = read_json(path)
    if fmt == "json":
        print(json.dumps(payload, indent=2, sort_keys=True))
    else:
        _print_preflight_text(payload)
        print(f"  Source:   {path}")
    return 0


def preflight_export(inv: Invocation) -> int:
    fmt = (inv.opts.get("format") or "json").lower()
    if fmt != "json":
        print("preflight export currently supports only --format json.")
        return 2

    src = latest_run_path(base=None)
    if not src:
        print("No preflight runs found to export.")
        return 1

    payload = read_json(src)
    run_id = payload.get("run_id", "preflight")

    out = inv.opts.get("out")
    if out:
        out_path = Path(out)
        if out_path.exists() and out_path.is_dir():
            dest = out_path / f"{run_id}.json"
        else:
            if str(out).endswith(("/", "\\")):
                out_path.mkdir(parents=True, exist_ok=True)
                dest = out_path / f"{run_id}.json"
            else:
                out_path.parent.mkdir(parents=True, exist_ok=True)
                dest = out_path
    else:
        dest = Path.cwd() / f"{run_id}.json"

    dest.write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
    print(f"Exported: {dest}")
    print(f"From:     {src}")
    return 0
