"""sshj.lastused — last-called recording + seeding (leaf-ish).

B2 step 3c: moved verbatim from sshj_cli.py (single-file era) — no
behavior change. Edges: jsonio (state files) and discover
(SSH_FLAG_ARGS for history parsing).
"""

import os
import shlex
import time

from .discover import SSH_FLAG_ARGS, HISTORY_SCAN_TAIL, tail_lines
from .jsonio import LAST_USED_FILE, LAST_SUCCESS_FILE, load_json, save_json


def load_last_used():
    """alias->epoch map, or {} if never recorded."""
    return load_json(LAST_USED_FILE, {})


def record_last_used(alias):
    """Stamp an alias's last-used time to now and persist."""
    d = load_last_used()
    d[alias] = time.time()
    save_json(LAST_USED_FILE, d)


def load_last_success():
    """alias->epoch of the last SUCCESSFUL connection, or {}."""
    return load_json(LAST_SUCCESS_FILE, {})


def record_last_success(alias):
    """Stamp an alias's last-success time to now and persist. Called only
    when ssh actually exits 0 — a failed attempt updates last_used (it was
    tried) but must not move the host up in last-success order."""
    d = load_last_success()
    d[alias] = time.time()
    save_json(LAST_SUCCESS_FILE, d)


def seed_from_history(hosts):
    """Seed last-used from shell history when none is recorded yet."""
    d = load_last_used()
    if d:
        return d
    hist = os.environ.get("HISTFILE") or os.path.expanduser("~/.bash_history")
    # H1: bounded tail — a multi-GB HISTFILE never loads into memory. The
    # trade-off: an ssh entry older than HISTORY_SCAN_TAIL lines is invisible
    # to the seed (acceptable: the seed only runs when nothing is recorded).
    lines = tail_lines(hist, HISTORY_SCAN_TAIL)
    by_alias = {h["alias"]: h["alias"] for h in hosts}
    by_target = {}
    for h in hosts:
        if h["hostname"]:
            by_target.setdefault(h["hostname"], h["alias"])
    ts = None
    try:
        fallback = os.path.getmtime(hist)
    except OSError:
        fallback = time.time()
    for ln in lines:
        if ln.startswith("#"):
            try:
                ts = int(ln[1:].strip())
            except ValueError:
                ts = None
            continue
        s = ln.strip()
        if not s:
            continue
        try:
            toks = shlex.split(s)
        except ValueError:
            continue
        if not toks or os.path.basename(toks[0]) != "ssh":
            continue
        i = 1
        while i < len(toks):
            t = toks[i]
            if t == "ssh":
                break
            if t.startswith("-"):
                if t in SSH_FLAG_ARGS:
                    i += 2
                else:
                    i += 1
            else:
                break
        if i >= len(toks):
            continue
        target = toks[i]
        alias = None
        if target in by_alias:
            alias = target
        elif "@" in target:
            hostpart = target.rpartition("@")[2].rsplit(":", 1)[0]
            alias = by_alias.get(hostpart) or by_target.get(hostpart)
        else:
            alias = by_target.get(target)
        if alias:
            d[alias] = max(d.get(alias, 0), ts if ts else fallback)
    if d:
        save_json(LAST_USED_FILE, d)
    return d


def human_age(sec):
    """Compact age: up to 3 digits + 1-char label (s/m/h/d/m/y)."""
    sec = max(0, int(sec))
    if sec < 60:
        return f"{sec}s"
    m = sec // 60
    if m < 60:
        return f"{m}m"
    h = sec // 3600
    if h < 24:
        return f"{h}h"
    d = sec // 86400
    if d < 30:
        return f"{d}d"
    mo = sec // 2592000
    if mo < 12:
        return f"{mo}m"
    return f"{sec // 31536000}y"


