from __future__ import annotations

import sqlite3
from datetime import datetime
from pathlib import Path

from app.config import DB_PATH, STORAGE_DIR
from app.db import connect


class BackupService:
    @property
    def backup_dir(self) -> Path:
        path = STORAGE_DIR / 'backups'
        path.mkdir(parents=True, exist_ok=True)
        return path

    def create(self) -> Path:
        if not DB_PATH.exists():
            raise FileNotFoundError('Database does not exist')
        stamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        target = self.backup_dir / f'database_{stamp}.sqlite3'

        # SQLite's online backup API safely includes WAL-backed changes and is
        # preferable to copying only the main database file while the app runs.
        source = connect()
        destination = sqlite3.connect(target)
        try:
            source.backup(destination)
            destination.execute('PRAGMA integrity_check')
            destination.commit()
        except Exception:
            destination.close()
            source.close()
            target.unlink(missing_ok=True)
            raise
        else:
            destination.close()
            source.close()
        try:
            target.chmod(0o600)
        except OSError:
            pass
        return target

    def list(self):
        result = []
        for path in sorted(self.backup_dir.glob('database_*.sqlite3'), reverse=True):
            stat = path.stat()
            result.append({'name': path.name, 'size': stat.st_size, 'mtime': datetime.fromtimestamp(stat.st_mtime).isoformat(timespec='seconds')})
        return result
