"""Tests for LibraryService"""

import pytest

from pathlib import Path

from sqlalchemy.ext.asyncio import AsyncSession

from chitai.schemas.library import LibraryCreate
from chitai.services import LibraryService
from chitai.database import models as m
from chitai.services.utils import DirectoryDoesNotExist


@pytest.mark.asyncio
class TestLibraryServiceCRUD:
    """Test CRUD operation for libraries."""

    async def test_create_library(
        self, library_service: LibraryService, tmp_path: Path
    ) -> None:
        """Test creating a library with a valid root path."""

        library_path = f"{tmp_path}/books"
        library_data = LibraryCreate(
            name="Test Library",
            root_path=library_path,
            path_template="{author}/{title}",
            read_only=False,
        )

        library = await library_service.create(library_data)

        assert library.name == "Test Library"
        assert library.root_path == library_path
        assert library.path_template == "{author}/{title}"
        assert library.description == None
        assert library.read_only == False

        # Check if directory was created
        assert Path(library.root_path).is_dir()

    async def test_create_library_root_path_permission_error(
        self, library_service: LibraryService, tmp_path: Path
    ) -> None:
        """Test creating a library with a root path that is not permitted."""

        # Change permissions on the temp path
        tmp_path.chmod(0o544)

        library_path = f"{tmp_path}/books"
        library_data = LibraryCreate(
            name="Test Library",
            root_path=library_path,
            path_template="{author}/{title}",
            read_only=False,
        )

        with pytest.raises(PermissionError) as exc_info:
            library = await library_service.create(library_data)

        # Check if directory was created
        assert not Path(library_path).exists()

        # Change permissions back
        tmp_path.chmod(0o755)

    async def test_create_library_read_only_path_exists(
        self, library_service: LibraryService, tmp_path: Path
    ) -> None:
        """Test creating a read-only library with a root path that exists."""

        # Create the path beforehand
        library_path = f"{tmp_path}/books"
        Path(library_path).mkdir()

        library_data = LibraryCreate(
            name="Test Library",
            root_path=library_path,
            path_template="{author}/{title}",
            read_only=True,
        )

        library = await library_service.create(library_data)

        assert library.name == "Test Library"
        assert library.root_path == library_path
        assert library.path_template == "{author}/{title}"
        assert library.description == None
        assert library.read_only == True

    async def test_create_library_read_only_nonexistent_path(
        self, library_service: LibraryService, tmp_path: Path
    ) -> None:
        """Test creating a read-only library with a nonexistent root path."""

        library_path = f"{tmp_path}/books"
        library_data = LibraryCreate(
            name="Test Library",
            root_path=library_path,
            path_template="{author}/{title}",
            read_only=True,
        )

        with pytest.raises(DirectoryDoesNotExist) as exc_info:
            await library_service.create(library_data)

        assert "Root directory" in str(exc_info.value)
        assert "must exist for a read-only library" in str(exc_info.value)

        # Check if directory was created
        assert not Path(library_path).exists()

    async def test_get_library(
        self, session: AsyncSession, library_service: LibraryService
    ) -> None:
        """Test retrieving a library."""

        # Add a library to the database
        library_data = m.Library(
            name="Testing Library",
            slug="testing-library",
            root_path="./books",
            path_template="{author}/{title}",
            description=None,
            read_only=False,
        )

        session.add(library_data)
        await session.commit()
        await session.refresh(library_data)

        library = await library_service.get(library_data.id)

        assert library is not None
        assert library.id == library_data.id
        assert library.name == "Testing Library"
        assert library.root_path == "./books"
        assert library.path_template == "{author}/{title}"
        assert library.description is None
        assert library.read_only == False

    # async def test_delete_library_keep_files(
    #     self, session: AsyncSession, library_service: LibraryService
    # ) -> None:
    #     """Test deletion of a library's metadata and associated entities."""
    #     raise NotImplementedError()

    # async def test_delete_library_delete_files(
    #     self, session: AsyncSession, library_service: LibraryService
    # ) -> None:
    #     """Test deletion of a library's metadata, associated enties, and files/directories."""
    #     raise NotImplementedError()
