"""
DB 자동 백업 유틸리티.

전략:
- 앱 시작 시 1일 1회만 백업 (last_backup_date 설정 키로 가드)
- 사용자 폴더(`~/.clockout_backups/`)에 회전 보관 (기본 7개)
- SQLite의 안전한 백업 API(sqlite3.Connection.backup) 사용 — 락 안전
"""
from __future__ import annotations
import os
import sqlite3
from datetime import date
from pathlib import Path
from typing import Optional

from core.settings_keys import LAST_BACKUP_DATE

DEFAULT_BACKUP_DIR = Path.home() / '.clockout_backups'
DEFAULT_KEEP = 7


def backup_db_if_needed(db, source_path: str = "database.db",
                        backup_dir: Optional[Path] = None,
                        keep: int = DEFAULT_KEEP) -> Optional[Path]:
    """오늘 첫 실행이면 백업 1개 만들고 오래된 것 회전.

    Args:
        db: Database 인스턴스 (set_setting/get_setting 사용)
        source_path: 원본 DB 파일 경로
        backup_dir: 백업 저장 디렉토리 (기본 ~/.clockout_backups)
        keep: 보관할 백업 개수

    Returns:
        생성된 백업 파일 경로, 또는 이미 오늘 백업했으면 None
    """
    today = date.today().isoformat()
    if db.get_setting(LAST_BACKUP_DATE, '') == today:
        return None

    src = Path(source_path)
    if not src.exists():
        return None

    target_dir = backup_dir or DEFAULT_BACKUP_DIR
    target_dir.mkdir(parents=True, exist_ok=True)
    target = target_dir / f"database-{today}.db"

    # SQLite 백업 API: WAL/락 환경에서도 안전한 일관성 있는 복사
    src_conn = sqlite3.connect(str(src))
    try:
        dest_conn = sqlite3.connect(str(target))
        try:
            src_conn.backup(dest_conn)
        finally:
            dest_conn.close()
    finally:
        src_conn.close()

    db.set_setting(LAST_BACKUP_DATE, today)
    _rotate(target_dir, keep)
    return target


def _rotate(directory: Path, keep: int) -> None:
    """오래된 백업 제거 — 최신 keep개만 유지"""
    files = sorted(
        (p for p in directory.glob('database-*.db') if p.is_file()),
        key=lambda p: p.stat().st_mtime,
        reverse=True,
    )
    for old in files[keep:]:
        try:
            old.unlink()
        except OSError as e:
            # 회전 실패 시 로그만 — 다음 실행에 재시도. 누적 시 디스크 압박 가능.
            from utils.debug_log import dlog
            dlog(f"backup rotation failed for {old}: {e}")
