#!/usr/bin/env python3
"""
Move Immich soft-deleted files from /opt/immich/el/ and /opt/immich/elv/
into the actual recycle bin (/opt/immich/recycle/) with proper DB entries.

For each file with location='recycle' in file_inventory:
  1. Move the file to /opt/immich/recycle/<uuid>.<ext>
  2. Insert a row into recycle_bin
  3. Delete from file_inventory
"""

import os
import shutil
import sys
import time
import uuid
from pathlib import Path

import psycopg2

APP_DB_DSN = "postgresql://media_downloader:PNsihOXvvuPwWiIvGlsc9Fh2YmMmB@localhost/media_downloader"
RECYCLE_DIR = Path("/opt/immich/recycle")
BATCH_SIZE = 500


def main():
    start = time.time()
    print("Moving Immich soft-deleted files to recycle bin")
    print("=" * 60)

    conn = psycopg2.connect(APP_DB_DSN)
    cur = conn.cursor()

    # Get all recycled entries from el/elv
    cur.execute("""
        SELECT id, file_path, filename, file_size, file_hash, created_date
        FROM file_inventory
        WHERE (file_path LIKE '/opt/immich/el/%' OR file_path LIKE '/opt/immich/elv/%')
          AND location = 'recycle'
        ORDER BY id
    """)
    rows = cur.fetchall()
    total = len(rows)
    print(f"  Found {total:,} recycled entries to move")

    if total == 0:
        print("  Nothing to do.")
        conn.close()
        return

    RECYCLE_DIR.mkdir(parents=True, exist_ok=True)

    moved = 0
    missing = 0
    errors = 0

    for i, (inv_id, file_path, filename, file_size, file_hash, created_date) in enumerate(rows):
        src = Path(file_path)

        if not src.exists():
            # File doesn't exist on disk — just remove from file_inventory
            cur.execute("DELETE FROM file_inventory WHERE id = %s", (inv_id,))
            missing += 1
            if missing <= 5:
                print(f"  MISSING (removed from DB): {file_path}")
            continue

        # Generate recycle path
        ext = src.suffix or ""
        recycle_id = str(uuid.uuid4())
        recycle_path = RECYCLE_DIR / f"{recycle_id}{ext}"

        try:
            # Get file mtime before moving
            mtime = src.stat().st_mtime
            actual_size = src.stat().st_size

            # Move the file
            shutil.move(str(src), str(recycle_path))

            # Insert into recycle_bin
            cur.execute("""
                INSERT INTO recycle_bin
                    (id, original_path, original_filename, recycle_path,
                     file_extension, file_size, original_mtime,
                     deleted_from, deleted_by, file_hash)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """, (
                recycle_id,
                file_path,
                filename,
                str(recycle_path),
                ext.lstrip(".") if ext else None,
                actual_size or file_size,
                mtime,
                "immich_deleted",
                "immich_migration",
                file_hash,
            ))

            # Delete from file_inventory
            cur.execute("DELETE FROM file_inventory WHERE id = %s", (inv_id,))

            moved += 1

        except Exception as e:
            errors += 1
            if errors <= 5:
                print(f"  ERROR moving {file_path}: {e}")

        if (i + 1) % BATCH_SIZE == 0:
            conn.commit()
            print(f"  Progress: {i + 1:,}/{total:,} — moved: {moved:,}, missing: {missing:,}, errors: {errors:,}")

    conn.commit()
    cur.close()
    conn.close()

    elapsed = time.time() - start
    print(f"\n  DONE in {elapsed:.1f}s:")
    print(f"    Moved to recycle: {moved:,}")
    print(f"    Missing on disk:  {missing:,}")
    print(f"    Errors:           {errors:,}")


if __name__ == "__main__":
    main()
