"""
Scanner service for initial library scan and per-user source root bootstrap.
"""
import os
import logging
from sqlalchemy import select

from app.database import AsyncSessionLocal
from app.models import SourceRoot
from app.models.user import User
from app.tasks.scan import scan_all_source_roots
from app.config import settings

logger = logging.getLogger(__name__)


async def bootstrap_user_source_root(user: User, session=None) -> None:
    """Create the media directory and a source root for a user.

    Called when a new user is created (by the admin or the setup endpoint).
    If the user already has a source root, this is a no-op.
    """
    own_session = session is None
    if own_session:
        session = AsyncSessionLocal()

    try:
        # Check if user already has a source root
        result = await session.execute(
            select(SourceRoot).where(SourceRoot.user_id == user.id)
        )
        if result.scalar_one_or_none() is not None:
            return

        os.makedirs(user.media_path, exist_ok=True)

        source_root = SourceRoot(
            name=f"{user.username}'s Library",
            path=user.media_path,
            user_id=user.id,
        )
        session.add(source_root)
        if own_session:
            await session.commit()
        else:
            await session.flush()

        logger.info(
            f"Bootstrapped source root for user '{user.username}': "
            f"{user.media_path}"
        )
    finally:
        if own_session:
            await session.close()


async def bootstrap_default_source_root() -> None:
    """Legacy bootstrap — for existing installs that have source roots
    without user_id (pre-auth migration). On fresh installs, source roots
    are created per-user via bootstrap_user_source_root. If there are
    already source roots in the DB, this is a no-op.
    """
    async with AsyncSessionLocal() as session:
        result = await session.execute(select(SourceRoot))
        if result.scalars().first() is not None:
            return  # Already have source roots.

        # No source roots and no users means fresh install — the setup
        # endpoint will create the first user + source root.
        user_count = (await session.execute(
            select(User)
        )).scalars().first()
        if user_count is None:
            logger.info(
                "No users or source roots — waiting for first-run setup."
            )
            return


async def start_initial_scan():
    """Start the initial library scan and optionally the file watcher.

    The file watcher uses a Redis lock to ensure only one instance runs
    across all workers, so it's safe to dispatch on every startup — only
    the first one will actually watch, the rest exit immediately.
    """
    try:
        scan_all_source_roots.delay()
        logger.info("Initial scan queued successfully")
    except Exception as e:
        logger.error(f"Failed to start initial scan: {e}")

    # Start the file watcher if enabled in config.
    from app.config import settings
    if settings.scanner.watch:
        try:
            from app.tasks.scan import watch_folders
            # Countdown gives the initial scan time to register source roots
            # before the watcher tries to load them.
            watch_folders.apply_async(countdown=10)
            logger.info("File watcher queued (Redis-locked, single instance)")
        except Exception as e:
            logger.warning(f"Could not queue file watcher: {e}")
