from __future__ import annotations

from functools import lru_cache
from pathlib import Path

from backend.app.config import Settings, get_settings
from backend.app.db.bookmark_repository import BookmarkRepository
from backend.app.db.history_repository import HistoryRepository
from backend.app.db.settings_repository import SettingsRepository
from backend.app.db.task_repository import TaskRepository
from backend.app.fs.filesystem_adapter import FilesystemAdapter
from backend.app.security.path_guard import PathGuard
from backend.app.services.bookmark_service import BookmarkService
from backend.app.services.browse_service import BrowseService
from backend.app.services.copy_task_service import CopyTaskService
from backend.app.services.archive_download_task_service import ArchiveDownloadTaskService
from backend.app.services.delete_task_service import DeleteTaskService
from backend.app.services.duplicate_task_service import DuplicateTaskService
from backend.app.services.file_ops_service import FileOpsService
from backend.app.services.history_service import HistoryService
from backend.app.services.move_task_service import MoveTaskService
from backend.app.services.search_service import SearchService
from backend.app.services.settings_service import SettingsService
from backend.app.services.task_service import TaskService
from backend.app.tasks_runner import TaskRunner


@lru_cache(maxsize=1)
def get_path_guard() -> PathGuard:
    settings: Settings = get_settings()
    return PathGuard(root_aliases=settings.root_aliases)


@lru_cache(maxsize=1)
def get_filesystem_adapter() -> FilesystemAdapter:
    return FilesystemAdapter()


@lru_cache(maxsize=1)
def get_task_repository() -> TaskRepository:
    settings: Settings = get_settings()
    return TaskRepository(db_path=settings.task_db_path)

@lru_cache(maxsize=1)
def get_bookmark_repository() -> BookmarkRepository:
    settings: Settings = get_settings()
    return BookmarkRepository(db_path=settings.task_db_path)


@lru_cache(maxsize=1)
def get_history_repository() -> HistoryRepository:
    settings: Settings = get_settings()
    return HistoryRepository(db_path=settings.task_db_path)


@lru_cache(maxsize=1)
def get_settings_repository() -> SettingsRepository:
    settings: Settings = get_settings()
    return SettingsRepository(db_path=settings.task_db_path)


@lru_cache(maxsize=1)
def get_task_runner() -> TaskRunner:
    return TaskRunner(
        repository=get_task_repository(),
        filesystem=get_filesystem_adapter(),
        history_repository=get_history_repository(),
    )


@lru_cache(maxsize=1)
def get_archive_artifact_root() -> str:
    settings: Settings = get_settings()
    return str(Path(settings.task_db_path).resolve().parent / "archive_tmp")


async def get_browse_service() -> BrowseService:
    return BrowseService(path_guard=get_path_guard(), filesystem=get_filesystem_adapter())


async def get_file_ops_service() -> FileOpsService:
    return FileOpsService(
        path_guard=get_path_guard(),
        filesystem=get_filesystem_adapter(),
        history_repository=get_history_repository(),
    )


async def get_archive_download_task_service() -> ArchiveDownloadTaskService:
    return ArchiveDownloadTaskService(
        path_guard=get_path_guard(),
        repository=get_task_repository(),
        runner=get_task_runner(),
        history_repository=get_history_repository(),
        file_ops_service=FileOpsService(
            path_guard=get_path_guard(),
            filesystem=get_filesystem_adapter(),
            history_repository=get_history_repository(),
        ),
        artifact_root=Path(get_archive_artifact_root()),
    )


async def get_task_service() -> TaskService:
    return TaskService(repository=get_task_repository(), history_repository=get_history_repository())


async def get_copy_task_service() -> CopyTaskService:
    return CopyTaskService(
        path_guard=get_path_guard(),
        repository=get_task_repository(),
        runner=get_task_runner(),
        history_repository=get_history_repository(),
    )


async def get_delete_task_service() -> DeleteTaskService:
    return DeleteTaskService(
        path_guard=get_path_guard(),
        repository=get_task_repository(),
        runner=get_task_runner(),
        history_repository=get_history_repository(),
    )


async def get_duplicate_task_service() -> DuplicateTaskService:
    return DuplicateTaskService(
        path_guard=get_path_guard(),
        repository=get_task_repository(),
        runner=get_task_runner(),
        history_repository=get_history_repository(),
    )


async def get_move_task_service() -> MoveTaskService:
    return MoveTaskService(
        path_guard=get_path_guard(),
        repository=get_task_repository(),
        runner=get_task_runner(),
        history_repository=get_history_repository(),
    )


async def get_bookmark_service() -> BookmarkService:
    return BookmarkService(path_guard=get_path_guard(), repository=get_bookmark_repository())


async def get_history_service() -> HistoryService:
    return HistoryService(repository=get_history_repository())


async def get_search_service() -> SearchService:
    return SearchService(path_guard=get_path_guard(), filesystem=get_filesystem_adapter())


async def get_settings_service() -> SettingsService:
    return SettingsService(repository=get_settings_repository(), path_guard=get_path_guard())
