# src/chitai/services/library.py

# Third-party libraries
from pathlib import Path
from advanced_alchemy.service import SQLAlchemyAsyncRepositoryService
from advanced_alchemy.repository import SQLAlchemyAsyncRepository
from advanced_alchemy import service
from advanced_alchemy.utils.text import slugify

# Local imports
from chitai.database.models.library import Library
from chitai.schemas.library import LibraryCreate, LibraryUpdate
from chitai.services.utils import (
    DirectoryDoesNotExist,
    create_directory,
    directory_exists,
)

from chitai.config import settings

class LibraryService(SQLAlchemyAsyncRepositoryService[Library]):
    """Service for managing libraries and their configuration."""

    class Repo(SQLAlchemyAsyncRepository[Library]):
        """Repository for Library entities."""

        model_type = Library

    repository_type = Repo

    async def create(self, library: LibraryCreate, **kwargs) -> Library:
        """
        Create a new library and initialize its filesystem structure.

        For writable libraries, creates the root directory and any missing parent directories.
        For read-only libraries, validates that the root directory already exists.

        Args:
            library: The library configuration to create.
            **kwargs: Additional keyword arguments passed to parent create.

        Returns:
            The created Library entity.

        Raises:
            DirectoryDoesNotExist: If a read-only library's root directory does not exist.
            OSError: If directory creation fails due to filesystem issues.
        """

        # TODO: What if a library root_path is a child of an existing library?
        if existing := await self.list(Library.root_path == library.root_path):
            raise ValueError(f"Library already exists at '{library.root_path}'")

        if library.read_only:
            # Validate read-only library directory exists
            if not await directory_exists(library.root_path):
                raise DirectoryDoesNotExist(
                    f"Root directory '{library.root_path}' must exist for a read-only library"
                )
           
            
        # TODO: Verify the read-only library has read permissions
        created_library = await super().create(
            service.schema_dump(library, exclude_unset=False), **kwargs
        )

        if not library.read_only:
            # Create directory for writable libraries
            await create_directory(library.root_path)
            # Create a consume directory
            await create_directory(Path(settings.consume_path) / Path(library.slug))

        return created_library
        



    # TODO: Implement library deletion and optional file deletion
    async def delete(
        self, item_id: int, delete_files: bool = False, **kwargs
    ) -> Library:
        """
        Delete a library and optionally delete its associated files from the filesystem.

        For writable libraries, can optionally delete the root directory and all its contents.
        Read-only libraries cannot have their files deleted through this method, as they are
        typically external or managed elsewhere.

        Args:
            item_id: The ID of the library to delete.
            delete_files: If True, delete the library's root directory and all files.
                            Cannot be True for read-only libraries. Defaults to False.
            **kwargs: Additional keyword arguments passed to parent delete method.

        Returns:
            The deleted Library entity.

        Raises:
            ValueError: If delete_files=True is specified for a read-only library.
            DirectoryDoesNotExist: If the library's root directory does not exist when attempting
                                    to delete files.
            OSError: If file deletion fails due to filesystem errors.

        """
        raise NotImplementedError()

    async def update(
        self,
        data: LibraryUpdate,
        item_id: int | None = None,
        **kwargs,
    ) -> Library:
        """
        Update a library's configuration and optionally move its files to a new root path.

        If the root_path is being changed and the library is not read-only, migrates all
        associated book files to the new location. Read-only libraries cannot have their
        files moved, and attempting to change their root_path will raise an error.

        Args:
            item_id: The ID of the library to update.
            data: LibraryUpdate configuration with updated library fields.
            **kwargs: Additional keyword arguments passed to parent update method.

        Returns:
            The updated Library entity.

        Raises:
            ValueError: If attempting to change root_path for a read-only library.
            DirectoryDoesNotExist: If the current library root directory does not exist
                                when attempting to migrate files.
            OSError: If file migration fails due to filesystem errors.
        """
        raise NotImplementedError()
