// src/application/services/bookmark_service.rs
use crate::application::error::ApplicationResult;
use crate::domain::bookmark::Bookmark;
use crate::domain::repositories::query::{BookmarkQuery, SortDirection};
use crate::domain::search::{HybridSearch, HybridSearchResult, SemanticSearch, SemanticSearchResult};
use crate::domain::tag::Tag;
use std::collections::HashSet;
use std::fmt::Debug;

/// Service interface for bookmark-related operations
pub trait BookmarkService: Send + Sync + Debug {
    /// Add a new bookmark
    fn add_bookmark(
        &self,
        url: &str,
        title: Option<&str>,
        description: Option<&str>,
        tags: Option<&HashSet<Tag>>,
        fetch_metadata: bool,
        embeddable: bool,
    ) -> ApplicationResult<Bookmark>;

    /// Delete a bookmark by ID
    fn delete_bookmark(&self, id: i32) -> ApplicationResult<bool>;

    /// Get a bookmark by ID
    fn get_bookmark(&self, id: i32) -> ApplicationResult<Option<Bookmark>>;

    fn set_bookmark_embeddable(&self, id: i32, embeddable: bool) -> ApplicationResult<Bookmark>;

    /// Update a bookmark's title and description
    fn update_bookmark(
        &self,
        bookmark: Bookmark,
        force_embedding: bool,
    ) -> ApplicationResult<Bookmark>;

    /// Add tags to a bookmark
    fn add_tags_to_bookmark(&self, id: i32, tags: &HashSet<Tag>) -> ApplicationResult<Bookmark>;

    /// Remove tags from a bookmark
    fn remove_tags_from_bookmark(
        &self,
        id: i32,
        tags: &HashSet<Tag>,
    ) -> ApplicationResult<Bookmark>;

    /// Replace all tags on a bookmark
    fn replace_bookmark_tags(&self, id: i32, tags: &HashSet<Tag>) -> ApplicationResult<Bookmark>;

    fn search_bookmarks_by_text(&self, query: &str) -> ApplicationResult<Vec<Bookmark>>;
    // Add a convenience method to create a query for text search

    // Replace the complex search_bookmarks method with a simpler interface
    fn search_bookmarks(&self, query: &BookmarkQuery) -> ApplicationResult<Vec<Bookmark>>;

    /// Perform semantic search with the given parameters
    fn semantic_search(
        &self,
        search: &SemanticSearch,
    ) -> ApplicationResult<Vec<SemanticSearchResult>>;

    /// Perform hybrid search combining FTS and semantic search with RRF fusion
    fn hybrid_search(
        &self,
        search: &HybridSearch,
    ) -> ApplicationResult<Vec<HybridSearchResult>>;

    /// Get bookmark by URL
    fn get_bookmark_by_url(&self, url: &str) -> ApplicationResult<Option<Bookmark>>;

    /// Get all bookmarks
    fn get_all_bookmarks(
        &self,
        sort_direction: Option<SortDirection>,
        limit: Option<usize>,
    ) -> ApplicationResult<Vec<Bookmark>>;

    /// Get random bookmarks
    fn get_random_bookmarks(&self, count: usize) -> ApplicationResult<Vec<Bookmark>>;

    /// Get bookmarks for forced backfill (all embeddable bookmarks except those with _imported_ tag)
    fn get_bookmarks_for_forced_backfill(&self) -> ApplicationResult<Vec<Bookmark>>;

    /// Check if bookmarks need embedding backfilling
    fn get_bookmarks_without_embeddings(&self) -> ApplicationResult<Vec<Bookmark>>;

    /// Record that a bookmark was accessed
    fn record_bookmark_access(&self, id: i32) -> ApplicationResult<Bookmark>;

    /// Bulk-create bookmarks from a JSON array file. Stores full content (url, title,
    /// description, tags). Skips bookmarks whose URL already exists. Does NOT support updates.
    /// Use case: agent bulk imports, migrations, seeding a database.
    fn load_json_bookmarks(&self, path: &str, dry_run: bool, embeddable: bool) -> ApplicationResult<usize>;

    /// Import files from directories with frontmatter metadata. Stores full content AND
    /// tracks source file (path, mtime, hash) for smart editing and change detection.
    /// Supports incremental updates and orphan deletion. Use case: indexing script/doc
    /// directories while keeping files as the source of truth.
    fn import_files(
        &self,
        paths: &[String],
        update: bool,
        delete_missing: bool,
        dry_run: bool,
        verbose: bool,
        base_path_name: Option<&str>,
        embeddable: bool,
    ) -> ApplicationResult<(usize, usize, usize)>; // Returns (added, updated, deleted)
}
