"""
Re-classify older AI suggestions that lack the new classification fields
(is_template_candidate, could_be_guide, customer_language).

Re-runs gpt-4o-mini classification on the original message and updates
the classification_json in place. Does NOT regenerate drafts.

Usage:
    venv/Scripts/python.exe scripts/backfill_reclassify.py [--limit N] [--dry-run]

Cost: ~$0.0002/suggestion (gpt-4o-mini classify only)
"""

import argparse
import json
import sys
import time

sys.path.insert(0, ".")

from supporthub.app.db import session_scope
from supporthub.app.models import AISuggestions, Tickets, AddonsMessages
from supporthub.app.services.ai_service import AIService


def get_pending(session):
    """Return suggestions missing the new classification fields."""
    all_sugg = (
        session.query(AISuggestions.id, AISuggestions.classification_json)
        .all()
    )
    pending_ids = []
    for sid, cjson in all_sugg:
        try:
            data = json.loads(cjson)
            if "is_template_candidate" not in data:
                pending_ids.append(sid)
        except (json.JSONDecodeError, TypeError):
            pending_ids.append(sid)
    return pending_ids


def main():
    parser = argparse.ArgumentParser(description="Re-classify old AI suggestions")
    parser.add_argument("--limit", type=int, default=0, help="Max suggestions to process (0=all)")
    parser.add_argument("--dry-run", action="store_true", help="Show count without processing")
    args = parser.parse_args()

    with session_scope() as session:
        pending_ids = get_pending(session)

        if args.limit > 0:
            pending_ids = pending_ids[:args.limit]

        total = len(pending_ids)
        est_cost = total * 0.0002
        print(f"Suggestions to re-classify: {total}")
        print(f"Estimated cost: ${est_cost:.4f}")

        if args.dry_run or total == 0:
            return

        ai = AIService()
        done = 0
        errors = 0
        t0 = time.time()

        for i, sid in enumerate(pending_ids, 1):
            try:
                suggestion = session.query(AISuggestions).filter_by(id=sid).one()
                ticket = session.query(Tickets).filter_by(id=suggestion.ticket_id).one()
                message = session.query(AddonsMessages).filter_by(id=suggestion.message_id).one()

                # Re-run classification (Call 1 only)
                summary, classification_obj, classification_json_str, intent = \
                    ai._run_classification(ticket, message, session)

                # Update in place — keep existing draft_reply, just refresh classification
                suggestion.summary = summary[:512]
                suggestion.classification_json = classification_json_str
                done += 1

            except Exception as exc:
                errors += 1
                print(f"  ERROR suggestion {sid}: {exc}")

            if i % 25 == 0 or i == total:
                elapsed = time.time() - t0
                rate = i / elapsed if elapsed > 0 else 0
                eta = (total - i) / rate if rate > 0 else 0
                print(
                    f"  [{i}/{total}] done={done} errors={errors} "
                    f"({rate:.1f}/s, ETA {eta:.0f}s)"
                )

            # Flush with retry for SQLite locking
            if i % 50 == 0:
                for attempt in range(5):
                    try:
                        session.flush()
                        break
                    except Exception as flush_exc:
                        if "database is locked" in str(flush_exc) and attempt < 4:
                            print(f"  DB locked, retrying flush ({attempt + 1}/5)...")
                            time.sleep(3)
                        else:
                            raise

        # Final flush with retry
        for attempt in range(5):
            try:
                session.flush()
                break
            except Exception as flush_exc:
                if "database is locked" in str(flush_exc) and attempt < 4:
                    print(f"  DB locked on final flush, retrying ({attempt + 1}/5)...")
                    time.sleep(3)
                else:
                    raise

        elapsed = time.time() - t0
        print(f"\nDone in {elapsed:.1f}s: {done} re-classified, {errors} errors")


if __name__ == "__main__":
    main()
