#!/usr/bin/env python3
"""PedQuiz management CLI.

Usage (inside container):
  python manage.py reset-password <email> <new-password>
  python manage.py list-users
  python manage.py reembed                         # Regenerate all question embeddings
  python manage.py extract <doc_id> <section_id>  # Run extraction from CLI
  python manage.py list-sections [doc_id]          # List documents/sections
  python manage.py jobs                            # Show recent extraction jobs
"""
import argparse
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))


def reset_password(email: str, new_password: str):
    from app.database import SessionLocal
    from app.models.user import User
    from app.utils.auth import get_password_hash
    if len(new_password) < 8:
        print("Error: Password must be at least 8 characters"); sys.exit(1)
    db = SessionLocal()
    try:
        user = db.query(User).filter(User.email == email).first()
        if not user:
            print(f"Error: No user found with email '{email}'"); sys.exit(1)
        user.hashed_password = get_password_hash(new_password)
        db.commit()
        print(f"Password reset for {user.email} (name={user.name!r}, role={user.role})")
    finally:
        db.close()


def list_users():
    from app.database import SessionLocal
    from app.models.user import User
    from app.models.email_verification import EmailVerification
    db = SessionLocal()
    try:
        users = db.query(User).order_by(User.created_at).all()
        print(f"{'ID':>4}  {'Email':40}  {'Role':12}  {'Verified':8}  Name")
        print("-" * 90)
        for u in users:
            v = db.query(EmailVerification).filter(EmailVerification.user_id == u.id).first()
            verified = "yes" if (v and v.verified_at) else "no"
            print(f"{u.id:>4}  {u.email:40}  {u.role:12}  {verified:8}  {u.name}")
    finally:
        db.close()


def reembed():
    from app.database import SessionLocal
    from app.models.question import Question
    from app.services import embedding_service
    db = SessionLocal()
    try:
        questions = db.query(Question).all()
        print(f"Re-embedding {len(questions)} questions...")
        ok = fail = 0
        for q in questions:
            q.embedding = None
            if embedding_service.embed_question(q):
                ok += 1
            else:
                fail += 1
        db.commit()
        print(f"Done: {ok} succeeded, {fail} failed")
    finally:
        db.close()


def list_sections(doc_id=None):
    from app.database import SessionLocal
    from app.models.pdf_document import PDFDocument
    from app.models.section import Section
    db = SessionLocal()
    try:
        docs_q = db.query(PDFDocument)
        if doc_id:
            docs_q = docs_q.filter(PDFDocument.id == int(doc_id))
        docs = docs_q.order_by(PDFDocument.id).all()
        for doc in docs:
            print(f"Doc {doc.id}: {doc.original_filename} ({doc.status}, {doc.total_pages or '?'} pages)")
            sections = db.query(Section).filter(Section.document_id == doc.id).all()
            if sections:
                for s in sections:
                    print(f"  Section {s.id}: {s.name!r}  pages {s.start_page}–{s.end_page}")
            else:
                print("  (no sections defined yet)")
    finally:
        db.close()


def extract(section_id: int, title: str, mode: str, email: str, background: bool):
    """Run quiz extraction — either in background (Celery) or inline (blocking)."""
    from app.database import SessionLocal
    from app.models.user import User
    from app.models.section import Section
    import uuid

    db = SessionLocal()
    try:
        section = db.query(Section).filter(Section.id == section_id).first()
        if not section:
            print(f"Error: Section {section_id} not found"); sys.exit(1)

        user = db.query(User).filter(User.email == email).first()
        if not user:
            print(f"Error: User '{email}' not found"); sys.exit(1)

        if not title:
            title = f"Quiz: {section.name}"

        print(f"Extracting from section {section_id}: {section.name!r} (pages {section.start_page}–{section.end_page})")
        print(f"Title: {title!r}  Mode: {mode}  User: {email}")

        if background:
            job_id = str(uuid.uuid4())
            try:
                from app.tasks.quiz_tasks import extract_quiz
                import redis as redis_lib
                from app.config import settings
                r = redis_lib.from_url(settings.REDIS_URL, decode_responses=True)
                r.set(f"extraction:status:{job_id}", "pending", ex=3600)
                r.set(f"extraction:job_title:{job_id}", title, ex=3600)
                r.lpush(f"extraction:user_jobs:{user.id}", job_id)
                r.expire(f"extraction:user_jobs:{user.id}", 86400)
                extract_quiz.delay(job_id=job_id, user_id=user.id, section_id=section_id,
                                   title=title, mode=mode, time_limit_minutes=None,
                                   model_id=None, question_category_id=None)
                print(f"\nJob started in background: {job_id}")
                print(f"Monitor: python manage.py jobs")
            except Exception as e:
                print(f"Error dispatching to Celery: {e}")
                print("Falling back to inline extraction...")
                _extract_inline(db, user, section_id, title, mode)
        else:
            _extract_inline(db, user, section_id, title, mode)
    finally:
        db.close()


def _extract_inline(db, user, section_id, title, mode):
    """Run extraction synchronously with live output."""
    from app.services.quiz_service import create_quiz_from_section
    print("\nRunning extraction (this may take several minutes for large sections)...")
    try:
        quiz = create_quiz_from_section(
            db=db, user_id=user.id, section_id=section_id,
            title=title, mode=mode,
        )
        print(f"\nDone! Quiz created: id={quiz.id}, title={quiz.title!r}, questions={quiz.questions_count}")
    except Exception as e:
        print(f"\nExtraction failed: {e}")
        sys.exit(1)


def show_jobs(user_email=None):
    import redis, json
    from app.config import settings
    from app.database import SessionLocal
    from app.models.user import User

    r = redis.from_url(settings.REDIS_URL, decode_responses=True)
    db = SessionLocal()
    try:
        if user_email:
            user = db.query(User).filter(User.email == user_email).first()
            if not user:
                print(f"User not found: {user_email}"); return
            users = [user]
        else:
            users = db.query(User).all()

        for user in users:
            job_ids = r.lrange(f"extraction:user_jobs:{user.id}", 0, 9)
            if not job_ids:
                continue
            print(f"\n{user.email}:")
            for jid in job_ids:
                status = r.get(f"extraction:status:{jid}") or "expired"
                title = r.get(f"extraction:job_title:{jid}") or "?"
                steps = r.lrange(f"extraction:steps:{jid}", 0, -1)
                quiz_id = r.get(f"extraction:quiz_id:{jid}")
                last = json.loads(steps[-1]).get("message", "") if steps else ""
                print(f"  [{status:10}] {title[:40]:40} steps={len(steps):3}"
                      + (f" quiz_id={quiz_id}" if quiz_id else "")
                      + (f"\n              {last[:80]}" if last else ""))
    finally:
        db.close()


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="PedQuiz management CLI")
    sub = parser.add_subparsers(dest="command")

    rp = sub.add_parser("reset-password", help="Reset a user password")
    rp.add_argument("email"); rp.add_argument("password")

    sub.add_parser("list-users", help="List all users")
    sub.add_parser("reembed", help="Regenerate all question embeddings")

    ls = sub.add_parser("list-sections", help="List documents and sections")
    ls.add_argument("doc_id", nargs="?", help="Optional: filter by document ID")

    ex = sub.add_parser("extract", help="Run quiz extraction from a section")
    ex.add_argument("section_id", type=int, help="Section ID to extract from")
    ex.add_argument("--title", default="", help="Quiz title (default: auto)")
    ex.add_argument("--mode", default="timed", choices=["timed", "learning"])
    ex.add_argument("--user", default="", help="User email to assign quiz to (default: first admin)")
    ex.add_argument("--bg", action="store_true", help="Run in background via Celery")

    jb = sub.add_parser("jobs", help="Show recent extraction jobs")
    jb.add_argument("--user", default=None, help="Filter by user email")

    args = parser.parse_args()

    if args.command == "reset-password":
        reset_password(args.email, args.password)
    elif args.command == "list-users":
        list_users()
    elif args.command == "reembed":
        reembed()
    elif args.command == "list-sections":
        list_sections(args.doc_id)
    elif args.command == "extract":
        email = args.user
        if not email:
            from app.database import SessionLocal
            from app.models.user import User
            db = SessionLocal()
            admin = db.query(User).filter(User.role == "admin").first()
            email = admin.email if admin else ""
            db.close()
        if not email:
            print("Error: No admin user found. Use --user <email>"); sys.exit(1)
        extract(args.section_id, args.title, args.mode, email, args.bg)
    elif args.command == "jobs":
        show_jobs(args.user)
    else:
        parser.print_help()
