"""
Startup cleanup of legacy extracted_images rows and files on disk.
"""
from __future__ import annotations

import os
from typing import List, Optional, Tuple

from sqlalchemy import text

from app.services.document_db_service import DocumentDbService

_EXTRACTED_PREFIXES = ("extracted_images_",)

# Bump when cleanup logic changes so a new full pass runs once per deploy.
_CLEANUP_TARGET_VERSION = 3
_CLEANUP_APPLIED_VERSION = 0


def _unlink(path: str) -> bool:
    if not path:
        return False
    try:
        if os.path.isfile(path):
            os.unlink(path)
            return True
    except OSError as exc:
        print(f"[CLEANUP] Could not delete {path}: {exc}")
    return False


def _unlink_tree_files(root: str) -> int:
    """Remove all files under *root* (not subdir names themselves)."""
    removed = 0
    if not root or not os.path.isdir(root):
        return removed
    for dirpath, _dirnames, filenames in os.walk(root):
        for name in filenames:
            full = os.path.join(dirpath, name)
            if _unlink(full):
                removed += 1
    return removed


def cleanup_all_extracted_images(
    db_file: str,
    extracted_folders: Optional[List[str]] = None,
) -> dict:
    """
    Delete every row in extracted_images and remove referenced files from disk.
    Optionally wipe known extracted_images_* folder trees for orphans.
    """
    stats = {
        "db_rows": 0,
        "files_removed": 0,
        "folder_files_removed": 0,
    }
    if not db_file:
        return stats

    paths: set = set()
    try:
        svc = DocumentDbService(db_file=db_file, agent_id=None)
        rows: List[Tuple] = svc.db.execute(
            text("SELECT id, image_path FROM extracted_images")
        ).fetchall()

        for row in rows:
            stats["db_rows"] += 1
            path = (row[1] or "").strip()
            if path:
                paths.add(path)

        for path in paths:
            if _unlink(path):
                stats["files_removed"] += 1

        svc.db.execute(text("DELETE FROM extracted_images"))
        svc.db.commit()
        svc.close()
    except Exception as exc:
        print(f"[CLEANUP] extracted_images DB cleanup failed: {exc}")
        return stats

    for folder in extracted_folders or []:
        stats["folder_files_removed"] += _unlink_tree_files(folder)

    cwd = os.getcwd()
    try:
        for name in os.listdir(cwd):
            if not any(name.startswith(p) for p in _EXTRACTED_PREFIXES):
                continue
            full = os.path.join(cwd, name)
            if os.path.isdir(full):
                stats["folder_files_removed"] += _unlink_tree_files(full)
    except OSError as exc:
        print(f"[CLEANUP] extracted folder scan failed: {exc}")

    print(
        f"[CLEANUP] extracted_images cleanup: db_rows={stats['db_rows']}, "
        f"files={stats['files_removed']}, folder_files={stats['folder_files_removed']}"
    )
    return stats


def cleanup_legacy_file_previews(
    db_file: str,
    preview_folder: Optional[str] = None,
) -> dict:
    """Remove document_images_/file_data preview PNGs and clear files.image_path columns."""
    stats = {"preview_files_removed": 0, "db_files_cleared": 0}
    if preview_folder:
        stats["preview_files_removed"] = _unlink_tree_files(preview_folder)
    if not db_file:
        return stats
    try:
        svc = DocumentDbService(db_file=db_file, agent_id=None)
        result = svc.db.execute(
            text(
                "UPDATE files SET image_path = '', thumbnail_path = '' "
                "WHERE COALESCE(image_path, '') != '' OR COALESCE(thumbnail_path, '') != ''"
            )
        )
        stats["db_files_cleared"] = result.rowcount or 0
        svc.db.commit()
        svc.close()
    except Exception as exc:
        print(f"[CLEANUP] legacy file preview cleanup failed: {exc}")
    print(
        f"[CLEANUP] legacy file previews: files={stats['preview_files_removed']}, "
        f"db_rows={stats['db_files_cleared']}"
    )
    return stats


def cleanup_extracted_images_once(
    db_file: str,
    extracted_folders: Optional[List[str]] = None,
    preview_folder: Optional[str] = None,
) -> dict:
    """Run full extracted_images cleanup at most once per process per target version."""
    global _CLEANUP_APPLIED_VERSION
    if _CLEANUP_APPLIED_VERSION >= _CLEANUP_TARGET_VERSION:
        return {"skipped": True, "version": _CLEANUP_APPLIED_VERSION}
    stats = cleanup_all_extracted_images(db_file, extracted_folders)
    stats.update(cleanup_legacy_file_previews(db_file, preview_folder))
    _CLEANUP_APPLIED_VERSION = _CLEANUP_TARGET_VERSION
    stats["version"] = _CLEANUP_APPLIED_VERSION
    return stats


# Backward-compatible alias
def cleanup_page_snapshots_once(
    db_file: str,
    extracted_folders: Optional[List[str]] = None,
) -> dict:
    return cleanup_extracted_images_once(db_file, extracted_folders)
