# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Email: Georgescottfoley@proton.me
# Licensed under the MIT License - see LICENSE file for details

"""
Training Pipeline CLI — familiar-train entry point

Run the automated training pipeline, check status, view stats, and verify chain.

Usage:
    familiar-train run                     # Full pipeline run
    familiar-train run --format sharegpt   # Custom export format
    familiar-train run --min-quality 0.7   # Higher quality threshold
    familiar-train run --min-records 0     # Skip record minimum
    familiar-train status                  # Latest run + history
    familiar-train stats                   # Training data statistics
    familiar-train stats --detailed        # With quality distribution
    familiar-train verify                  # Chain integrity check
"""

from __future__ import annotations

import argparse
import json
import logging
import sys

logger = logging.getLogger(__name__)


def create_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(
        prog="familiar-train",
        description="Familiar training pipeline — curate, export, and verify training data",
    )
    sub = p.add_subparsers(dest="command", required=True)

    # ── run ───────────────────────────────────────────────────────────────
    run_p = sub.add_parser("run", help="Run the full training pipeline")
    run_p.add_argument(
        "--format",
        default="alpaca",
        choices=["alpaca", "sharegpt", "openai"],
        help="Export format (default: alpaca)",
    )
    run_p.add_argument(
        "--min-quality",
        type=float,
        default=0.5,
        help="Minimum quality score (default: 0.5)",
    )
    run_p.add_argument(
        "--min-records",
        type=int,
        default=10,
        help="Minimum records for quality gate (default: 10)",
    )
    run_p.add_argument(
        "--min-diversity",
        type=int,
        default=2,
        help="Minimum distinct source types (default: 2)",
    )
    run_p.add_argument(
        "--no-memories",
        action="store_true",
        default=False,
        help="Skip markdown memory collection",
    )

    # ── status ────────────────────────────────────────────────────────────
    sub.add_parser("status", help="Show latest pipeline run and history")

    # ── stats ─────────────────────────────────────────────────────────────
    stats_p = sub.add_parser("stats", help="Show training data statistics")
    stats_p.add_argument(
        "--detailed",
        action="store_true",
        default=False,
        help="Show quality distribution and provenance chain",
    )

    # ── verify ────────────────────────────────────────────────────────────
    sub.add_parser("verify", help="Verify genesis chain integrity")

    return p


def cmd_run(args):
    """Run the full training pipeline."""
    from familiar.skills.training.pipeline import PipelineConfig, run_pipeline

    config = PipelineConfig(
        min_records=args.min_records,
        min_avg_quality=args.min_quality,
        min_diversity=args.min_diversity,
        export_format=args.format,
        include_memories=not args.no_memories,
        min_quality=args.min_quality,
    )

    print(
        f"Starting training pipeline (format={config.export_format}, "
        f"min_quality={config.min_quality})..."
    )
    print()

    run = run_pipeline(config)

    if run.status == "complete":
        print(f"Pipeline complete (run_id={run.run_id})")
        print()
        for key, value in run.stats.items():
            if isinstance(value, str):
                print(f"  {key}: {value}")
            elif isinstance(value, dict):
                print(f"  {key}:")
                for k, v in value.items():
                    if isinstance(v, dict):
                        print(f"    {k}: {json.dumps(v)}")
                    else:
                        print(f"    {k}: {v}")
    elif run.status == "failed":
        print(f"Pipeline failed (run_id={run.run_id})")
        print(f"  Error: {run.error}")
        sys.exit(1)
    else:
        print(f"Pipeline ended with status: {run.status}")


def cmd_status(args):
    """Show pipeline status and history."""
    from familiar.skills.training.pipeline import get_pipeline_status

    status = get_pipeline_status()
    total = status.get("total_runs", 0)

    if total == 0:
        print("No pipeline runs yet. Run 'familiar-train run' to start.")
        return

    print(f"Pipeline Status ({total} total runs)")
    print()

    latest = status.get("latest_run")
    if latest:
        print("Latest run:")
        print(f"  run_id     : {latest.get('run_id')}")
        print(f"  status     : {latest.get('status')}")
        print(f"  started    : {latest.get('started_at')}")
        print(f"  completed  : {latest.get('completed_at', 'n/a')}")
        if latest.get("error"):
            print(f"  error      : {latest.get('error')}")

    history = status.get("history", [])
    if len(history) > 1:
        print()
        print("Recent history:")
        for h in reversed(history[:-1]):
            err = f" ({h['error'][:40]})" if h.get("error") else ""
            print(f"  {h['run_id']} | {h['status']:10s} | {h['started_at'][:19]}{err}")


def cmd_stats(args):
    """Show training data statistics."""
    from familiar.skills.training.skill import training_stats

    result = training_stats({"detailed": args.detailed})
    print(result)


def cmd_verify(args):
    """Verify genesis chain integrity."""
    try:
        from familiar.skills.training.bridge import get_chain_status
    except ImportError:
        print("Genesis block module not available.")
        sys.exit(1)

    status = get_chain_status()

    if not status.get("initialized"):
        print("No genesis block found. Chain not initialized.")
        print("Run 'create_genesis' tool to initialize the provenance chain.")
        return

    print("Genesis Chain Verification")
    print()
    print(f"  Genesis hash  : {status['genesis_hash'][:16]}...")
    print(f"  Chain length  : {status['chain_length']} blocks")

    latest = status.get("latest_block")
    if latest:
        print(f"  Latest block  : #{latest['index']} ({latest['type']})")
        print(f"  Latest hash   : {latest['hash'][:16]}...")
        print(f"  Latest time   : {latest['timestamp'][:19]}")

    integrity = status.get("integrity", {})
    if integrity:
        if integrity.get("valid"):
            print()
            print("  Integrity: VALID — all blocks verified")
        else:
            print()
            print(f"  Integrity: INVALID — {integrity.get('error', 'unknown error')}")
            sys.exit(1)


def cli_main():
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    )
    parser = create_parser()
    args = parser.parse_args()

    if args.command == "run":
        cmd_run(args)
    elif args.command == "status":
        cmd_status(args)
    elif args.command == "stats":
        cmd_stats(args)
    elif args.command == "verify":
        cmd_verify(args)


if __name__ == "__main__":
    cli_main()
