"""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 is_migration_legacy_files_completed(db: AsyncSession) -> bool:
        """Check if legacy key/data file migration has been completed.
        
        Args:
            db: Database session
            
        Returns:
            True if legacy migration is completed, False otherwise
        """
        settings = await SystemSettingsService.get_or_create(db)
        return settings.migration_legacy_files_completed

    @staticmethod
    async def mark_migration_legacy_files_completed(
        db: AsyncSession,
        timestamp: Optional[datetime] = None
    ) -> None:
        """Mark the legacy key/data file migration as completed.
        
        Args:
            db: Database session
            timestamp: Optional timestamp to set, defaults to current time
        """
        settings = await SystemSettingsService.get_or_create(db)
        settings.migration_legacy_files_completed = True
        settings.last_scan_timestamp = timestamp or datetime.now(timezone.utc)
        await db.commit()
        logger.info("Marked legacy files migration as completed")

    @staticmethod
    async def is_legacy_key_cleanup_completed(db: AsyncSession) -> bool:
        """Check if legacy key file cleanup has been completed.

        Args:
            db: Database session

        Returns:
            True if cleanup is completed, False otherwise
        """
        settings = await SystemSettingsService.get_or_create(db)
        return settings.legacy_key_cleanup_completed

    @staticmethod
    async def mark_legacy_key_cleanup_completed(
        db: AsyncSession,
        timestamp: Optional[datetime] = None
    ) -> None:
        """Mark the legacy key file cleanup as completed.

        Args:
            db: Database session
            timestamp: Optional timestamp to set, defaults to current time
        """
        settings = await SystemSettingsService.get_or_create(db)
        settings.legacy_key_cleanup_completed = True
        settings.last_scan_timestamp = timestamp or datetime.now(timezone.utc)
        await db.commit()
        logger.info("Marked legacy key file cleanup as 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.migration_legacy_files_completed = False
        settings.legacy_key_cleanup_completed = False
        settings.last_scan_timestamp = None
        await db.commit()
        logger.info("Reset all scan completion flags")
