"""System settings service for managing application-level configuration. This module provides services for managing system-wide settings and state, including tracking initial setup completion status. """ from __future__ import annotations from datetime import datetime, timezone from typing import Optional import structlog from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.server.database.models import SystemSettings logger = structlog.get_logger(__name__) class SystemSettingsService: """Service for managing system settings.""" @staticmethod async def get_or_create(db: AsyncSession) -> SystemSettings: """Get the system settings record, creating it if it doesn't exist. Only one system settings record should exist in the database. Args: db: Database session Returns: SystemSettings instance """ # Try to get existing settings stmt = select(SystemSettings).limit(1) result = await db.execute(stmt) settings = result.scalar_one_or_none() if settings is None: # Create new settings with defaults settings = SystemSettings( initial_scan_completed=False, initial_nfo_scan_completed=False, initial_media_scan_completed=False, ) db.add(settings) await db.commit() await db.refresh(settings) logger.info("Created new system settings record") return settings @staticmethod async def is_initial_scan_completed(db: AsyncSession) -> bool: """Check if the initial anime folder scan has been completed. Args: db: Database session Returns: True if initial scan is completed, False otherwise """ settings = await SystemSettingsService.get_or_create(db) return settings.initial_scan_completed @staticmethod async def mark_initial_scan_completed( db: AsyncSession, timestamp: Optional[datetime] = None ) -> None: """Mark the initial anime folder scan as completed. Args: db: Database session timestamp: Optional timestamp to set, defaults to current time """ settings = await SystemSettingsService.get_or_create(db) settings.initial_scan_completed = True settings.last_scan_timestamp = timestamp or datetime.now(timezone.utc) await db.commit() logger.info("Marked initial scan as completed") @staticmethod async def is_initial_nfo_scan_completed(db: AsyncSession) -> bool: """Check if the initial NFO scan has been completed. Args: db: Database session Returns: True if initial NFO scan is completed, False otherwise """ settings = await SystemSettingsService.get_or_create(db) return settings.initial_nfo_scan_completed @staticmethod async def mark_initial_nfo_scan_completed( db: AsyncSession, timestamp: Optional[datetime] = None ) -> None: """Mark the initial NFO scan as completed. Args: db: Database session timestamp: Optional timestamp to set, defaults to current time """ settings = await SystemSettingsService.get_or_create(db) settings.initial_nfo_scan_completed = True if timestamp: settings.last_scan_timestamp = timestamp await db.commit() logger.info("Marked initial NFO scan as completed") @staticmethod async def is_initial_media_scan_completed(db: AsyncSession) -> bool: """Check if the initial media scan has been completed. Args: db: Database session Returns: True if initial media scan is completed, False otherwise """ settings = await SystemSettingsService.get_or_create(db) return settings.initial_media_scan_completed @staticmethod async def mark_initial_media_scan_completed( db: AsyncSession, timestamp: Optional[datetime] = None ) -> None: """Mark the initial media scan as completed. Args: db: Database session timestamp: Optional timestamp to set, defaults to current time """ settings = await SystemSettingsService.get_or_create(db) settings.initial_media_scan_completed = True if timestamp: settings.last_scan_timestamp = timestamp await db.commit() logger.info("Marked initial media scan as completed") @staticmethod async def reset_all_scans(db: AsyncSession) -> None: """Reset all scan completion flags (for testing or re-setup). Args: db: Database session """ settings = await SystemSettingsService.get_or_create(db) settings.initial_scan_completed = False settings.initial_nfo_scan_completed = False settings.initial_media_scan_completed = False settings.last_scan_timestamp = None await db.commit() logger.info("Reset all scan completion flags")