#!/usr/bin/env python3
"""odysseus-sessions — shell wrapper for chat sessions.

    odysseus-sessions list [--archived] [--folder F] [--limit N]
    odysseus-sessions show SESSION_ID
    odysseus-sessions archive SESSION_ID
    odysseus-sessions unarchive SESSION_ID
    odysseus-sessions delete SESSION_ID         # hard-delete (irreversible)
"""

from __future__ import annotations
import sys
import os, sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "_lib"))
from cli import quiet_logs, emit, fail, common_parser, run, REPO_ROOT as _REPO_ROOT
quiet_logs()

import argparse, json, logging, os, sys
from pathlib import Path

try:
    from core.database import SessionLocal, Session as DbSession
    quiet_logs()
except ModuleNotFoundError as e:
    sys.stderr.write(f"error: {e}\nhint: run from repo root with venv active.\n")
    sys.exit(2)


def _serialize(s: "DbSession") -> dict:
    def _int_or_zero(value) -> int:
        try:
            return int(value or 0)
        except (TypeError, ValueError):
            return 0

    return {
        "id": s.id,
        "name": s.name,
        "model": s.model,
        "endpoint_url": s.endpoint_url,
        "owner": s.owner or "",
        "folder": s.folder or "",
        "archived": bool(s.archived),
        "rag": bool(s.rag),
        "is_important": bool(s.is_important),
        "message_count": _int_or_zero(s.message_count),
        "total_input_tokens": _int_or_zero(s.total_input_tokens),
        "total_output_tokens": _int_or_zero(s.total_output_tokens),
        "last_accessed": s.last_accessed.isoformat() if s.last_accessed else "",
        "created_at": s.created_at.isoformat() if s.created_at else "",
    }


def cmd_list(args):
    db = SessionLocal()
    try:
        q = db.query(DbSession)
        if not args.archived:
            q = q.filter(DbSession.archived == False)  # noqa: E712
        elif args.archived == "only":
            q = q.filter(DbSession.archived == True)  # noqa: E712
        if args.folder:
            q = q.filter(DbSession.folder == args.folder)
        q = q.order_by(DbSession.last_accessed.desc()).limit(args.limit)
        emit([_serialize(s) for s in q.all()], args)
    finally:
        db.close()


def cmd_show(args):
    db = SessionLocal()
    try:
        s = db.get(DbSession, args.id)
        if not s:
            fail(f"no session with id {args.id!r}")
        emit(_serialize(s), args)
    finally:
        db.close()


def cmd_archive(args):
    _set_archived(args, True)


def cmd_unarchive(args):
    _set_archived(args, False)


def _set_archived(args, archived: bool):
    db = SessionLocal()
    try:
        s = db.get(DbSession, args.id)
        if not s:
            fail(f"no session with id {args.id!r}")
        s.archived = archived
        db.commit()
        emit({"ok": True, "id": s.id, "archived": s.archived}, args)
    finally:
        db.close()


def cmd_delete(args):
    if not args.yes:
        fail("delete is irreversible — pass --yes to confirm")
    db = SessionLocal()
    try:
        s = db.get(DbSession, args.id)
        if not s:
            fail(f"no session with id {args.id!r}")
        snap = _serialize(s)
        db.delete(s)
        db.commit()
        emit({"ok": True, "deleted": snap}, args)
    finally:
        db.close()


def _build_parser():
    common = argparse.ArgumentParser(add_help=False)
    common.add_argument("--pretty", action="store_true")

    p = argparse.ArgumentParser(prog="odysseus-sessions", parents=[common])
    sub = p.add_subparsers(dest="cmd", required=True)

    pl = sub.add_parser("list", parents=[common])
    pl.add_argument("--archived", nargs="?", const=True, default=False,
                    help="include archived; --archived only = only archived")
    pl.add_argument("--folder")
    pl.add_argument("--limit", type=int, default=50)
    pl.set_defaults(func=cmd_list)

    psh = sub.add_parser("show", parents=[common])
    psh.add_argument("id")
    psh.set_defaults(func=cmd_show)

    pa = sub.add_parser("archive", parents=[common])
    pa.add_argument("id")
    pa.set_defaults(func=cmd_archive)

    pu = sub.add_parser("unarchive", parents=[common])
    pu.add_argument("id")
    pu.set_defaults(func=cmd_unarchive)

    pd = sub.add_parser("delete", parents=[common])
    pd.add_argument("id")
    pd.add_argument("--yes", action="store_true", help="confirm deletion")
    pd.set_defaults(func=cmd_delete)

    return p


if __name__ == "__main__":
    sys.exit(run(_build_parser()))
