from __future__ import annotations

from datetime import datetime
from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile


BASE_DIR = Path(__file__).resolve().parents[1]
SNAPSHOT_DIR = BASE_DIR / "code_backups"
KEEP_LATEST = 10

INCLUDE_SUFFIXES = {".py", ".md", ".txt", ".bat", ".json", ".yml", ".yaml", ".ini", ".spec", ".sh"}
INCLUDE_FILENAMES = {".gitignore", "requirements.txt"}
EXCLUDE_DIRS = {
    ".venv",
    "__pycache__",
    "backups",
    "code_backups",
    "build",
    "dist",
    "debug",
    "restored_backups",
}
EXCLUDE_PREFIXES = (".venv_broken_",)


def should_include(path: Path) -> bool:
    if path.name in INCLUDE_FILENAMES:
        return True
    return path.suffix.lower() in INCLUDE_SUFFIXES


def iter_project_files() -> list[Path]:
    files: list[Path] = []
    for path in BASE_DIR.rglob("*"):
        if path.is_dir():
            continue
        relative_parts = path.relative_to(BASE_DIR).parts
        if any(part in EXCLUDE_DIRS for part in relative_parts):
            continue
        if any(any(part.startswith(prefix) for prefix in EXCLUDE_PREFIXES) for part in relative_parts):
            continue
        if should_include(path):
            files.append(path)
    return sorted(files)


def cleanup_old_backups() -> None:
    backups = sorted(
        SNAPSHOT_DIR.glob("po_internal_code_*.zip"),
        key=lambda p: p.stat().st_mtime,
        reverse=True,
    )
    for old_file in backups[KEEP_LATEST:]:
        old_file.unlink(missing_ok=True)


def create_code_backup() -> Path:
    SNAPSHOT_DIR.mkdir(parents=True, exist_ok=True)
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    archive_path = SNAPSHOT_DIR / f"po_internal_code_{timestamp}.zip"

    with ZipFile(archive_path, "w", compression=ZIP_DEFLATED) as archive:
        for file_path in iter_project_files():
            archive.write(file_path, arcname=file_path.relative_to(BASE_DIR))

    cleanup_old_backups()
    return archive_path


if __name__ == "__main__":
    backup_path = create_code_backup()
    print(backup_path)
