import argparse
import json
import sqlite3
from pathlib import Path

try:
    from scripts.crop_books import (
        CONFIDENCE_THRESHOLD,
        UNCROPPED_IMAGE_IDS,
        build_variant as build_cropped_variant,
        ensure_columns,
        source_path,
    )
except ImportError:
    from crop_books import (
        CONFIDENCE_THRESHOLD,
        UNCROPPED_IMAGE_IDS,
        build_variant as build_cropped_variant,
        ensure_columns,
        source_path,
    )


DEFAULT_DB = Path(__file__).resolve().parents[1] / "books.db"
DEFAULT_IMAGES = Path(r"C:\Users\ignac\OneDrive\Pictures\selected_libros")
DEFAULT_OUTPUT = Path(__file__).resolve().parents[1] / "optimized_images"


def build_variant(src: Path, dest: Path, max_side: int, quality: int, threshold: float):
    return build_cropped_variant(src, dest, max_side, quality, threshold)


def main():
    parser = argparse.ArgumentParser(description="Generate optimized Bibliothek web images")
    parser.add_argument("--db", type=Path, default=DEFAULT_DB)
    parser.add_argument("--images", type=Path, default=DEFAULT_IMAGES)
    parser.add_argument("--out", type=Path, default=DEFAULT_OUTPUT)
    parser.add_argument("--view-max", type=int, default=1600)
    parser.add_argument("--thumb-max", type=int, default=420)
    parser.add_argument("--quality", type=int, default=84)
    parser.add_argument("--threshold", type=float, default=CONFIDENCE_THRESHOLD)
    args = parser.parse_args()

    args.out.mkdir(parents=True, exist_ok=True)
    manifest_path = args.out / "manifest.json"

    conn = sqlite3.connect(str(args.db))
    conn.row_factory = sqlite3.Row
    ensure_columns(conn)

    rows = conn.execute("SELECT id, source_folder, source_filename FROM book_images ORDER BY id").fetchall()

    manifest = []
    for row in rows:
        image_id = int(row["id"])
        folder = row["source_folder"]
        filename = row["source_filename"]
        src = source_path(args.images, folder, filename)
        if not src.exists():
            print(f"Skipping missing file: {src}")
            continue

        storage_path = f"view/{image_id:04d}.jpg"
        thumb_storage_path = f"thumb/{image_id:04d}.jpg"
        view_dest = args.out / storage_path
        thumb_dest = args.out / thumb_storage_path

        result = build_cropped_variant(src, view_dest, args.view_max, args.quality, args.threshold, image_id=image_id)
        build_cropped_variant(src, thumb_dest, args.thumb_max, args.quality, args.threshold, image_id=image_id)

        conn.execute(
            "UPDATE book_images SET storage_path = ?, thumb_storage_path = ? WHERE id = ?",
            (storage_path, thumb_storage_path, image_id),
        )

        manifest.append(
            {
                "id": image_id,
                "source_folder": folder,
                "source_filename": filename,
                "storage_path": storage_path,
                "thumb_storage_path": thumb_storage_path,
                "crop_box": list(result.box),
                "crop_method": result.method,
                "crop_confidence": result.confidence,
                "forced_uncropped": image_id in UNCROPPED_IMAGE_IDS,
                "view_bytes": view_dest.stat().st_size,
                "thumb_bytes": thumb_dest.stat().st_size,
            }
        )

    conn.commit()
    conn.close()

    manifest_path.write_text(json.dumps(manifest, indent=2), encoding="utf-8")
    total_bytes = sum(item["view_bytes"] + item["thumb_bytes"] for item in manifest)
    print(
        json.dumps(
            {
                "generated": len(manifest),
                "output_dir": str(args.out),
                "manifest": str(manifest_path),
                "total_mb": round(total_bytes / 1024 / 1024, 2),
            },
            indent=2,
        )
    )


if __name__ == "__main__":
    main()
