use rusqlite::Connection;
use serde::Serialize;

use crate::crypto::encryption::{encrypt_data_with_user_key, decrypt_data_with_user_key};
use crate::crypto::key_manager::get_user_encryption_key;
use crate::domains::act::repo as act_repo;
use crate::domains::book::repo as book_repo;
use crate::domains::book::service::{
    BookActSummariesTable, BookAIGuideLineTable, BookChapterContentTable, BookChaptersTable,
    BookChapterInfosTable, BookCharactersTable, BookCharactersAttributesTable, BookGuideLineTable,
    BookIncidentsTable, BookIssuesTable, BookLocationTable, BookPlotPointsTable, BookSpellsTable,
    BookSpellTagsTable, BookWorldTable, BookWorldElementsTable, CompleteBook,
    LocationElementTable, LocationSubElementTable, BookSyncCompare, SyncedBookTools, SyncedIncident, SyncedPlotPoint, SyncedIssue, SyncedActSummary,
    SyncedGuideLine, SyncedAIGuideLine, SyncedSpell, SyncedSpellTag,
    SyncedSeries, SyncedSeriesBook, SyncedSeriesCharacter, SyncedSeriesCharacterAttribute,
    SyncedSeriesWorld, SyncedSeriesWorldElement, SyncedSeriesLocation,
    SyncedSeriesLocationElement, SyncedSeriesLocationSubElement, SyncedSeriesSpell,
    SyncedSeriesSpellTag,
};
use crate::domains::chapter::repo as chapter_repo;
use crate::domains::chapter_content::repo as chapter_content_repo;
use crate::domains::character::repo as character_repo;
use crate::domains::guideline::repo as guideline_repo;
use crate::domains::incident::repo as incident_repo;
use crate::domains::issue::repo as issue_repo;
use crate::domains::location::repo as location_repo;
use crate::domains::plotpoint::repo as plotpoint_repo;
use crate::domains::series::repo as series_repo;
use crate::domains::series_character::repo as series_character_repo;
use crate::domains::series_location::repo as series_location_repo;
use crate::domains::series_spell::repo as series_spell_repo;
use crate::domains::series_world::repo as series_world_repo;
use crate::domains::spell::repo as spell_repo;
use crate::domains::spell_tag::repo as spell_tag_repo;
use crate::domains::world::repo as world_repo;
use crate::error::AppResult;
use crate::shared::types::Lang;

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedChapterContent {
    pub id: String,
    pub last_update: i64,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedChapterInfo {
    pub id: String,
    pub last_update: i64,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedCharacterAttribute {
    pub id: String,
    pub name: String,
    pub last_update: i64,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedLocationElement {
    pub id: String,
    pub name: String,
    pub last_update: i64,
    pub sub_elements: Vec<SyncedLocationSubElement>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedLocationSubElement {
    pub id: String,
    pub name: String,
    pub last_update: i64,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedWorldElement {
    pub id: String,
    pub name: String,
    pub last_update: i64,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedChapterFull {
    pub id: String,
    pub name: String,
    pub last_update: i64,
    pub contents: Vec<SyncedChapterContent>,
    pub info: Option<SyncedChapterInfo>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedCharacterFull {
    pub id: String,
    pub name: String,
    pub last_update: i64,
    pub attributes: Vec<SyncedCharacterAttribute>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedLocationFull {
    pub id: String,
    pub name: String,
    pub last_update: i64,
    pub elements: Vec<SyncedLocationElement>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedWorldFull {
    pub id: String,
    pub name: String,
    pub last_update: i64,
    pub elements: Vec<SyncedWorldElement>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncedBookFull {
    pub id: String,
    pub book_type: String,
    pub title: String,
    pub sub_title: Option<String>,
    pub last_update: i64,
    pub chapters: Vec<SyncedChapterFull>,
    pub characters: Vec<SyncedCharacterFull>,
    pub locations: Vec<SyncedLocationFull>,
    pub worlds: Vec<SyncedWorldFull>,
    pub incidents: Vec<SyncedIncident>,
    pub plot_points: Vec<SyncedPlotPoint>,
    pub issues: Vec<SyncedIssue>,
    pub act_summaries: Vec<SyncedActSummary>,
    pub guide_line: Option<SyncedGuideLine>,
    pub ai_guide_line: Option<SyncedAIGuideLine>,
    pub book_tools: Option<SyncedBookTools>,
    pub spells: Vec<SyncedSpell>,
    pub spell_tags: Vec<SyncedSpellTag>,
}

/// Retrieves a complete book with all its associated entities for synchronization.
/// Decrypts all encrypted fields using the user's encryption key.
/// * `conn` - Database connection
/// * `user_id` - The unique identifier of the user
/// * `sync_compare_data` - Object containing IDs of entities to retrieve for sync comparison
/// * `lang` - The language for error messages
/// Returns a CompleteBook object with all decrypted data.
pub fn get_complete_sync_book(conn: &Connection, user_id: &str, sync_compare_data: &BookSyncCompare, lang: Lang) -> AppResult<CompleteBook> {
    let user_encryption_key: String = get_user_encryption_key(user_id)?;
    let mut decrypted_books: Vec<book_repo::EritBooksTable> = Vec::new();
    let mut decrypted_chapters: Vec<BookChaptersTable> = Vec::new();
    let mut decrypted_plot_points: Vec<BookPlotPointsTable> = Vec::new();
    let mut decrypted_incidents: Vec<BookIncidentsTable> = Vec::new();
    let mut decrypted_chapter_contents: Vec<BookChapterContentTable> = Vec::new();
    let mut decrypted_chapter_infos: Vec<BookChapterInfosTable> = Vec::new();
    let mut decrypted_characters: Vec<BookCharactersTable> = Vec::new();
    let mut decrypted_character_attributes: Vec<BookCharactersAttributesTable> = Vec::new();
    let mut decrypted_locations: Vec<BookLocationTable> = Vec::new();
    let mut decrypted_location_elements: Vec<LocationElementTable> = Vec::new();
    let mut decrypted_location_sub_elements: Vec<LocationSubElementTable> = Vec::new();
    let mut decrypted_worlds: Vec<BookWorldTable> = Vec::new();
    let mut decrypted_world_elements: Vec<BookWorldElementsTable> = Vec::new();
    let mut decrypted_act_summaries: Vec<BookActSummariesTable> = Vec::new();
    let mut decrypted_guide_lines: Vec<BookGuideLineTable> = Vec::new();
    let mut decrypted_ai_guide_lines: Vec<BookAIGuideLineTable> = Vec::new();
    let mut decrypted_issues: Vec<BookIssuesTable> = Vec::new();
    let mut decrypted_spells: Vec<BookSpellsTable> = Vec::new();
    let mut decrypted_spell_tags: Vec<BookSpellTagsTable> = Vec::new();

    let act_summary_ids: &Vec<String> = &sync_compare_data.act_summaries;
    let chapter_ids: &Vec<String> = &sync_compare_data.chapters;
    let plot_point_ids: &Vec<String> = &sync_compare_data.plot_points;
    let incident_ids: &Vec<String> = &sync_compare_data.incidents;
    let chapter_content_ids: &Vec<String> = &sync_compare_data.chapter_contents;
    let chapter_info_ids: &Vec<String> = &sync_compare_data.chapter_infos;
    let character_ids: &Vec<String> = &sync_compare_data.characters;
    let character_attribute_ids: &Vec<String> = &sync_compare_data.character_attributes;
    let location_ids: &Vec<String> = &sync_compare_data.locations;
    let location_element_ids: &Vec<String> = &sync_compare_data.location_elements;
    let location_sub_element_ids: &Vec<String> = &sync_compare_data.location_sub_elements;
    let world_ids: &Vec<String> = &sync_compare_data.worlds;
    let world_element_ids: &Vec<String> = &sync_compare_data.world_elements;
    let issue_ids: &Vec<String> = &sync_compare_data.issues;
    let spell_ids: &Vec<String> = &sync_compare_data.spells;
    let spell_tag_ids: &Vec<String> = &sync_compare_data.spell_tags;

    if !act_summary_ids.is_empty() {
        for act_summary_id in act_summary_ids {
            let act_summary_results: Vec<act_repo::BookActSummariesTable> = act_repo::fetch_complete_act_summary_by_id(conn, act_summary_id, lang)?;
            if !act_summary_results.is_empty() {
                let act_summary_record = &act_summary_results[0];
                decrypted_act_summaries.push(BookActSummariesTable {
                    act_sum_id: act_summary_record.act_sum_id.clone(),
                    book_id: act_summary_record.book_id.clone(),
                    user_id: act_summary_record.user_id.clone(),
                    act_index: act_summary_record.act_index,
                    summary: if let Some(ref summary) = act_summary_record.summary { if summary.is_empty() { None } else { Some(decrypt_data_with_user_key(summary, &user_encryption_key)?) } } else { None },
                    last_update: act_summary_record.last_update,
                });
            }
        }
    }

    if !chapter_ids.is_empty() {
        for chapter_id in chapter_ids {
            let chapter_results: Vec<chapter_repo::BookChaptersTable> = chapter_repo::fetch_complete_chapter_by_id(conn, chapter_id, lang)?;
            if !chapter_results.is_empty() {
                let chapter_record = &chapter_results[0];
                decrypted_chapters.push(BookChaptersTable {
                    chapter_id: chapter_record.chapter_id.clone(),
                    book_id: chapter_record.book_id.clone(),
                    author_id: chapter_record.author_id.clone(),
                    title: decrypt_data_with_user_key(&chapter_record.title, &user_encryption_key)?,
                    hashed_title: chapter_record.hashed_title.clone(),
                    words_count: chapter_record._words_count,
                    chapter_order: chapter_record.chapter_order,
                    last_update: chapter_record.last_update,
                });
            }
        }
    }

    if !plot_point_ids.is_empty() {
        for plot_point_id in plot_point_ids {
            let plot_point_results: Vec<plotpoint_repo::BookPlotPointsTable> = plotpoint_repo::fetch_complete_plot_point_by_id(conn, plot_point_id, lang)?;
            if !plot_point_results.is_empty() {
                let plot_point_record = &plot_point_results[0];
                decrypted_plot_points.push(BookPlotPointsTable {
                    plot_point_id: plot_point_record.plot_point_id.clone(),
                    title: decrypt_data_with_user_key(&plot_point_record.title, &user_encryption_key)?,
                    hashed_title: plot_point_record.hashed_title.clone(),
                    summary: if let Some(ref summary) = plot_point_record.summary { Some(decrypt_data_with_user_key(summary, &user_encryption_key)?) } else { None },
                    linked_incident_id: plot_point_record.linked_incident_id.clone(),
                    author_id: plot_point_record.author_id.clone(),
                    book_id: plot_point_record._book_id.clone(),
                    last_update: plot_point_record.last_update,
                });
            }
        }
    }

    if !incident_ids.is_empty() {
        for incident_id in incident_ids {
            let incident_results: Vec<incident_repo::BookIncidentsTable> = incident_repo::fetch_complete_incident_by_id(conn, incident_id, lang)?;
            if !incident_results.is_empty() {
                let incident_record = &incident_results[0];
                decrypted_incidents.push(BookIncidentsTable {
                    incident_id: incident_record.incident_id.clone(),
                    author_id: incident_record.author_id.clone(),
                    book_id: incident_record.book_id.clone(),
                    title: decrypt_data_with_user_key(&incident_record.title, &user_encryption_key)?,
                    hashed_title: incident_record.hashed_title.clone(),
                    summary: if let Some(ref summary) = incident_record.summary { Some(decrypt_data_with_user_key(summary, &user_encryption_key)?) } else { None },
                    last_update: incident_record.last_update,
                });
            }
        }
    }

    if !chapter_content_ids.is_empty() {
        for chapter_content_id in chapter_content_ids {
            let chapter_content_results: Vec<chapter_content_repo::BookChapterContentTable> = chapter_content_repo::fetch_complete_chapter_content_by_id(conn, chapter_content_id, lang)?;
            if !chapter_content_results.is_empty() {
                let chapter_content_record = &chapter_content_results[0];
                let decrypted_content: Option<serde_json::Value> = if let Some(ref content) = chapter_content_record.content {
                    let decrypted: String = decrypt_data_with_user_key(content, &user_encryption_key)?;
                    serde_json::from_str(&decrypted).ok()
                } else { None };
                decrypted_chapter_contents.push(BookChapterContentTable {
                    content_id: chapter_content_record.content_id.clone(),
                    chapter_id: chapter_content_record.chapter_id.clone(),
                    author_id: chapter_content_record.author_id.clone(),
                    version: chapter_content_record.version,
                    content: decrypted_content,
                    words_count: Some(chapter_content_record._words_count),
                    time_on_it: Some(chapter_content_record._time_on_it),
                    last_update: chapter_content_record.last_update,
                });
            }
        }
    }

    if !chapter_info_ids.is_empty() {
        for chapter_info_id in chapter_info_ids {
            let chapter_info_results: Vec<chapter_repo::BookChapterInfosTable> = chapter_repo::fetch_complete_chapter_info_by_id(conn, chapter_info_id, lang)?;
            if !chapter_info_results.is_empty() {
                let chapter_info_record = &chapter_info_results[0];
                decrypted_chapter_infos.push(BookChapterInfosTable {
                    chapter_info_id: chapter_info_record._chapter_info_id.clone(),
                    chapter_id: chapter_info_record.chapter_id.clone(),
                    act_id: chapter_info_record._act_id,
                    incident_id: chapter_info_record._incident_id.clone(),
                    plot_point_id: chapter_info_record._plot_point_id.clone(),
                    book_id: chapter_info_record._book_id.clone(),
                    author_id: chapter_info_record.author_id.clone(),
                    summary: if let Some(ref summary) = chapter_info_record.summary { Some(decrypt_data_with_user_key(summary, &user_encryption_key)?) } else { None },
                    goal: if let Some(ref goal) = chapter_info_record.goal { Some(decrypt_data_with_user_key(goal, &user_encryption_key)?) } else { None },
                    last_update: chapter_info_record.last_update,
                });
            }
        }
    }

    if !character_ids.is_empty() {
        for character_id in character_ids {
            let character_results: Vec<character_repo::BookCharactersTable> = character_repo::fetch_complete_character_by_id(conn, character_id, lang)?;
            if !character_results.is_empty() {
                let character_record = &character_results[0];
                decrypted_characters.push(BookCharactersTable {
                    character_id: character_record.character_id.clone(),
                    book_id: character_record.book_id.clone(),
                    user_id: character_record.user_id.clone(),
                    first_name: decrypt_data_with_user_key(&character_record.first_name, &user_encryption_key)?,
                    last_name: if let Some(ref last_name) = character_record.last_name { Some(decrypt_data_with_user_key(last_name, &user_encryption_key)?) } else { None },
                    nickname: if let Some(ref nickname) = character_record.nickname { Some(decrypt_data_with_user_key(nickname, &user_encryption_key)?) } else { None },
                    age: if let Some(ref age) = character_record.age { Some(decrypt_data_with_user_key(age, &user_encryption_key)?) } else { None },
                    gender: if let Some(ref gender) = character_record.gender { Some(decrypt_data_with_user_key(gender, &user_encryption_key)?) } else { None },
                    species: if let Some(ref species) = character_record.species { Some(decrypt_data_with_user_key(species, &user_encryption_key)?) } else { None },
                    nationality: if let Some(ref nationality) = character_record.nationality { Some(decrypt_data_with_user_key(nationality, &user_encryption_key)?) } else { None },
                    status: if let Some(ref status) = character_record.status { Some(decrypt_data_with_user_key(status, &user_encryption_key)?) } else { None },
                    title: if let Some(ref title) = character_record.title { Some(decrypt_data_with_user_key(title, &user_encryption_key)?) } else { None },
                    category: decrypt_data_with_user_key(&character_record.category, &user_encryption_key)?,
                    image: if let Some(ref image) = character_record.image { Some(decrypt_data_with_user_key(image, &user_encryption_key)?) } else { None },
                    role: if let Some(ref role) = character_record.role { Some(decrypt_data_with_user_key(role, &user_encryption_key)?) } else { None },
                    biography: if let Some(ref biography) = character_record.biography { Some(decrypt_data_with_user_key(biography, &user_encryption_key)?) } else { None },
                    history: if let Some(ref history) = character_record.history { Some(decrypt_data_with_user_key(history, &user_encryption_key)?) } else { None },
                    speech_pattern: if let Some(ref speech_pattern) = character_record.speech_pattern { Some(decrypt_data_with_user_key(speech_pattern, &user_encryption_key)?) } else { None },
                    catchphrase: if let Some(ref catchphrase) = character_record.catchphrase { Some(decrypt_data_with_user_key(catchphrase, &user_encryption_key)?) } else { None },
                    residence: if let Some(ref residence) = character_record.residence { Some(decrypt_data_with_user_key(residence, &user_encryption_key)?) } else { None },
                    notes: if let Some(ref notes) = character_record.notes { Some(decrypt_data_with_user_key(notes, &user_encryption_key)?) } else { None },
                    color: if let Some(ref color) = character_record.color { Some(decrypt_data_with_user_key(color, &user_encryption_key)?) } else { None },
                    last_update: character_record.last_update,
                });
            }
        }
    }

    if !character_attribute_ids.is_empty() {
        for character_attribute_id in character_attribute_ids {
            let character_attribute_results: Vec<character_repo::BookCharactersAttributesTable> = character_repo::fetch_complete_character_attribute_by_id(conn, character_attribute_id, lang)?;
            if !character_attribute_results.is_empty() {
                let character_attribute_record = &character_attribute_results[0];
                decrypted_character_attributes.push(BookCharactersAttributesTable {
                    attr_id: character_attribute_record.attr_id.clone(),
                    character_id: character_attribute_record.character_id.clone(),
                    user_id: character_attribute_record.user_id.clone(),
                    attribute_name: decrypt_data_with_user_key(&character_attribute_record.attribute_name, &user_encryption_key)?,
                    attribute_value: decrypt_data_with_user_key(&character_attribute_record.attribute_value, &user_encryption_key)?,
                    last_update: character_attribute_record.last_update,
                });
            }
        }
    }

    if !location_ids.is_empty() {
        for location_id in location_ids {
            let location_results: Vec<location_repo::BookLocationTable> = location_repo::fetch_complete_location_by_id(conn, location_id, lang)?;
            if !location_results.is_empty() {
                let location_record = &location_results[0];
                decrypted_locations.push(BookLocationTable {
                    loc_id: location_record.loc_id.clone(),
                    book_id: location_record.book_id.clone(),
                    user_id: location_record.user_id.clone(),
                    loc_name: decrypt_data_with_user_key(&location_record.loc_name, &user_encryption_key)?,
                    loc_original_name: location_record.loc_original_name.clone(),
                    last_update: location_record.last_update,
                });
            }
        }
    }

    if !location_element_ids.is_empty() {
        for location_element_id in location_element_ids {
            let location_element_results: Vec<location_repo::LocationElementTable> = location_repo::fetch_complete_location_element_by_id(conn, location_element_id, lang)?;
            if !location_element_results.is_empty() {
                let location_element_record = &location_element_results[0];
                decrypted_location_elements.push(LocationElementTable {
                    element_id: location_element_record.element_id.clone(),
                    location: location_element_record.location.clone(),
                    user_id: location_element_record.user_id.clone(),
                    element_name: decrypt_data_with_user_key(&location_element_record.element_name, &user_encryption_key)?,
                    original_name: location_element_record.original_name.clone(),
                    element_description: if let Some(ref element_description) = location_element_record.element_description { Some(decrypt_data_with_user_key(element_description, &user_encryption_key)?) } else { None },
                    last_update: location_element_record.last_update,
                });
            }
        }
    }

    if !location_sub_element_ids.is_empty() {
        for location_sub_element_id in location_sub_element_ids {
            let location_sub_element_results: Vec<location_repo::LocationSubElementTable> = location_repo::fetch_complete_location_sub_element_by_id(conn, location_sub_element_id, lang)?;
            if !location_sub_element_results.is_empty() {
                let location_sub_element_record = &location_sub_element_results[0];
                decrypted_location_sub_elements.push(LocationSubElementTable {
                    sub_element_id: location_sub_element_record.sub_element_id.clone(),
                    element_id: location_sub_element_record.element_id.clone(),
                    user_id: location_sub_element_record.user_id.clone(),
                    sub_elem_name: decrypt_data_with_user_key(&location_sub_element_record.sub_elem_name, &user_encryption_key)?,
                    original_name: location_sub_element_record.original_name.clone(),
                    sub_elem_description: if let Some(ref sub_elem_description) = location_sub_element_record.sub_elem_description { Some(decrypt_data_with_user_key(sub_elem_description, &user_encryption_key)?) } else { None },
                    last_update: location_sub_element_record.last_update,
                });
            }
        }
    }

    if !world_ids.is_empty() {
        for world_id in world_ids {
            let world_results: Vec<world_repo::BookWorldTable> = world_repo::fetch_complete_world_by_id(conn, world_id, lang)?;
            if !world_results.is_empty() {
                let world_record = &world_results[0];
                decrypted_worlds.push(BookWorldTable {
                    world_id: world_record.world_id.clone(),
                    name: decrypt_data_with_user_key(&world_record.name, &user_encryption_key)?,
                    hashed_name: world_record.hashed_name.clone(),
                    author_id: world_record.author_id.clone(),
                    book_id: world_record.book_id.clone(),
                    history: if let Some(ref history) = world_record.history { Some(decrypt_data_with_user_key(history, &user_encryption_key)?) } else { None },
                    politics: if let Some(ref politics) = world_record.politics { Some(decrypt_data_with_user_key(politics, &user_encryption_key)?) } else { None },
                    economy: if let Some(ref economy) = world_record.economy { Some(decrypt_data_with_user_key(economy, &user_encryption_key)?) } else { None },
                    religion: if let Some(ref religion) = world_record.religion { Some(decrypt_data_with_user_key(religion, &user_encryption_key)?) } else { None },
                    languages: if let Some(ref languages) = world_record.languages { Some(decrypt_data_with_user_key(languages, &user_encryption_key)?) } else { None },
                    last_update: world_record.last_update,
                });
            }
        }
    }

    if !world_element_ids.is_empty() {
        for world_element_id in world_element_ids {
            let world_element_results: Vec<world_repo::BookWorldElementsTable> = world_repo::fetch_complete_world_element_by_id(conn, world_element_id, lang)?;
            if !world_element_results.is_empty() {
                let world_element_record = &world_element_results[0];
                decrypted_world_elements.push(BookWorldElementsTable {
                    element_id: world_element_record.element_id.clone(),
                    world_id: world_element_record.world_id.clone(),
                    user_id: world_element_record.user_id.clone(),
                    element_type: world_element_record.element_type,
                    name: decrypt_data_with_user_key(&world_element_record.name, &user_encryption_key)?,
                    original_name: world_element_record.original_name.clone(),
                    description: if let Some(ref description) = world_element_record.description { Some(decrypt_data_with_user_key(description, &user_encryption_key)?) } else { None },
                    last_update: world_element_record.last_update,
                });
            }
        }
    }

    if !issue_ids.is_empty() {
        for issue_id in issue_ids {
            let issue_results: Vec<issue_repo::BookIssuesTable> = issue_repo::fetch_complete_issue_by_id(conn, issue_id, lang)?;
            if !issue_results.is_empty() {
                let issue_record = &issue_results[0];
                decrypted_issues.push(BookIssuesTable {
                    issue_id: issue_record.issue_id.clone(),
                    author_id: issue_record.author_id.clone(),
                    book_id: issue_record.book_id.clone(),
                    name: decrypt_data_with_user_key(&issue_record.name, &user_encryption_key)?,
                    hashed_issue_name: issue_record.hashed_issue_name.clone(),
                    last_update: issue_record.last_update,
                });
            }
        }
    }

    if sync_compare_data.guide_line {
        let guideline_results: Vec<guideline_repo::BookGuideLineTable> = guideline_repo::fetch_book_guide_line_table(conn, user_id, &sync_compare_data.id, lang)?;
        if !guideline_results.is_empty() {
            let guideline_record = &guideline_results[0];
            decrypted_guide_lines.push(BookGuideLineTable {
                user_id: guideline_record.user_id.clone(),
                book_id: guideline_record.book_id.clone(),
                tone: if let Some(ref tone) = guideline_record.tone { Some(decrypt_data_with_user_key(tone, &user_encryption_key)?) } else { None },
                atmosphere: if let Some(ref atmosphere) = guideline_record.atmosphere { Some(decrypt_data_with_user_key(atmosphere, &user_encryption_key)?) } else { None },
                writing_style: if let Some(ref writing_style) = guideline_record.writing_style { Some(decrypt_data_with_user_key(writing_style, &user_encryption_key)?) } else { None },
                themes: if let Some(ref themes) = guideline_record.themes { Some(decrypt_data_with_user_key(themes, &user_encryption_key)?) } else { None },
                symbolism: if let Some(ref symbolism) = guideline_record.symbolism { Some(decrypt_data_with_user_key(symbolism, &user_encryption_key)?) } else { None },
                motifs: if let Some(ref motifs) = guideline_record.motifs { Some(decrypt_data_with_user_key(motifs, &user_encryption_key)?) } else { None },
                narrative_voice: if let Some(ref narrative_voice) = guideline_record.narrative_voice { Some(decrypt_data_with_user_key(narrative_voice, &user_encryption_key)?) } else { None },
                pacing: if let Some(ref pacing) = guideline_record.pacing { Some(decrypt_data_with_user_key(pacing, &user_encryption_key)?) } else { None },
                intended_audience: if let Some(ref intended_audience) = guideline_record.intended_audience { Some(decrypt_data_with_user_key(intended_audience, &user_encryption_key)?) } else { None },
                key_messages: if let Some(ref key_messages) = guideline_record.key_messages { Some(decrypt_data_with_user_key(key_messages, &user_encryption_key)?) } else { None },
                last_update: guideline_record.last_update,
            });
        }
    }

    if sync_compare_data.ai_guide_line {
        let ai_guideline_results: Vec<guideline_repo::BookAIGuideLineTable> = guideline_repo::fetch_book_ai_guide_line(conn, user_id, &sync_compare_data.id, lang)?;
        if !ai_guideline_results.is_empty() {
            let ai_guideline_record = &ai_guideline_results[0];
            decrypted_ai_guide_lines.push(BookAIGuideLineTable {
                user_id: ai_guideline_record.user_id.clone(),
                book_id: ai_guideline_record.book_id.clone(),
                global_resume: if let Some(ref global_resume) = ai_guideline_record.global_resume { Some(decrypt_data_with_user_key(global_resume, &user_encryption_key)?) } else { None },
                themes: if let Some(ref themes) = ai_guideline_record.themes { Some(decrypt_data_with_user_key(themes, &user_encryption_key)?) } else { None },
                verbe_tense: ai_guideline_record.verbe_tense,
                narrative_type: ai_guideline_record.narrative_type,
                langue: ai_guideline_record.langue,
                dialogue_type: ai_guideline_record.dialogue_type,
                tone: if let Some(ref tone) = ai_guideline_record.tone { Some(decrypt_data_with_user_key(tone, &user_encryption_key)?) } else { None },
                atmosphere: if let Some(ref atmosphere) = ai_guideline_record.atmosphere { Some(decrypt_data_with_user_key(atmosphere, &user_encryption_key)?) } else { None },
                current_resume: if let Some(ref current_resume) = ai_guideline_record.current_resume { Some(decrypt_data_with_user_key(current_resume, &user_encryption_key)?) } else { None },
                last_update: ai_guideline_record.last_update,
            });
        }
    }

    if !spell_tag_ids.is_empty() {
        for spell_tag_id in spell_tag_ids {
            let spell_tag_record: Option<spell_tag_repo::BookSpellTagsTable> = spell_tag_repo::fetch_spell_tag_table_by_id(conn, user_id, spell_tag_id, lang)?;
            if let Some(spell_tag_record) = spell_tag_record {
                decrypted_spell_tags.push(BookSpellTagsTable {
                    tag_id: spell_tag_record.tag_id,
                    book_id: spell_tag_record.book_id,
                    user_id: spell_tag_record.user_id,
                    name: decrypt_data_with_user_key(&spell_tag_record.name, &user_encryption_key)?,
                    name_hash: spell_tag_record.name_hash,
                    color: spell_tag_record.color,
                    last_update: spell_tag_record.last_update,
                });
            }
        }
    }

    if !spell_ids.is_empty() {
        for spell_id in spell_ids {
            let spell_record: Option<spell_repo::BookSpellsTable> = spell_repo::fetch_spell_table_by_id(conn, user_id, spell_id, lang)?;
            if let Some(spell_record) = spell_record {
                decrypted_spells.push(BookSpellsTable {
                    spell_id: spell_record.spell_id,
                    book_id: spell_record.book_id,
                    user_id: spell_record.user_id,
                    name: decrypt_data_with_user_key(&spell_record.name, &user_encryption_key)?,
                    name_hash: spell_record.name_hash,
                    description: if let Some(ref description) = spell_record.description { if description.is_empty() { None } else { Some(decrypt_data_with_user_key(description, &user_encryption_key)?) } } else { None },
                    appearance: if let Some(ref appearance) = spell_record.appearance { if appearance.is_empty() { None } else { Some(decrypt_data_with_user_key(appearance, &user_encryption_key)?) } } else { None },
                    tags: if let Some(ref tags) = spell_record.tags { if tags.is_empty() { None } else { Some(decrypt_data_with_user_key(tags, &user_encryption_key)?) } } else { None },
                    power_level: if let Some(ref power_level) = spell_record.power_level { if power_level.is_empty() { None } else { Some(decrypt_data_with_user_key(power_level, &user_encryption_key)?) } } else { None },
                    components: if let Some(ref components) = spell_record.components { if components.is_empty() { None } else { Some(decrypt_data_with_user_key(components, &user_encryption_key)?) } } else { None },
                    limitations: if let Some(ref limitations) = spell_record.limitations { if limitations.is_empty() { None } else { Some(decrypt_data_with_user_key(limitations, &user_encryption_key)?) } } else { None },
                    notes: if let Some(ref notes) = spell_record.notes { Some(decrypt_data_with_user_key(notes, &user_encryption_key)?) } else { None },
                    last_update: spell_record.last_update,
                });
            }
        }
    }

    let book_results: Vec<book_repo::EritBooksTable> = book_repo::fetch_complete_book_by_id(conn, &sync_compare_data.id, lang)?;
    if !book_results.is_empty() {
        let book_record = &book_results[0];
        decrypted_books.push(book_repo::EritBooksTable {
            book_id: book_record.book_id.clone(),
            book_type: book_record.book_type.clone(),
            author_id: book_record.author_id.clone(),
            title: decrypt_data_with_user_key(&book_record.title, &user_encryption_key)?,
            hashed_title: book_record.hashed_title.clone(),
            sub_title: if let Some(ref sub_title) = book_record.sub_title { Some(decrypt_data_with_user_key(sub_title, &user_encryption_key)?) } else { None },
            hashed_sub_title: book_record.hashed_sub_title.clone(),
            summary: if let Some(ref summary) = book_record.summary { Some(decrypt_data_with_user_key(summary, &user_encryption_key)?) } else { None },
            serie_id: book_record.serie_id,
            desired_release_date: book_record.desired_release_date.clone(),
            desired_word_count: book_record.desired_word_count,
            words_count: book_record.words_count,
            cover_image: if let Some(ref cover_image) = book_record.cover_image { Some(decrypt_data_with_user_key(cover_image, &user_encryption_key)?) } else { None },
            last_update: book_record.last_update,
        });
    }

    let book_tools_result: Option<book_repo::BookToolsTable> = book_repo::fetch_book_tools(conn, user_id, &sync_compare_data.id, lang)?;
    let book_tools: Vec<book_repo::BookToolsTable> = if let Some(book_tools_row) = book_tools_result { vec![book_tools_row] } else { vec![] };

    Ok(CompleteBook {
        erit_books: decrypted_books,
        act_summaries: decrypted_act_summaries,
        ai_guide_line: decrypted_ai_guide_lines,
        chapters: decrypted_chapters,
        chapter_contents: decrypted_chapter_contents,
        chapter_infos: decrypted_chapter_infos,
        characters: decrypted_characters,
        character_attributes: decrypted_character_attributes,
        guide_line: decrypted_guide_lines,
        incidents: decrypted_incidents,
        issues: decrypted_issues,
        locations: decrypted_locations,
        plot_points: decrypted_plot_points,
        worlds: decrypted_worlds,
        world_elements: decrypted_world_elements,
        location_elements: decrypted_location_elements,
        location_sub_elements: decrypted_location_sub_elements,
        book_tools,
        spells: decrypted_spells,
        spell_tags: decrypted_spell_tags,
    })
}

/// Synchronizes a complete book from the server to the local client database.
/// Encrypts all data before storing and handles both insert and update operations.
/// * `conn` - Database connection
/// * `user_id` - The unique identifier of the user
/// * `complete_book` - The complete book data received from the server
/// * `lang` - The language for error messages
/// Returns true if sync was successful, false otherwise.
pub fn sync_book_from_server_to_client(conn: &Connection, user_id: &str, complete_book: &CompleteBook, lang: Lang) -> AppResult<bool> {
    let user_encryption_key: String = get_user_encryption_key(user_id)?;

    let server_act_summaries: &Vec<BookActSummariesTable> = &complete_book.act_summaries;
    let server_chapters: &Vec<BookChaptersTable> = &complete_book.chapters;
    let server_plot_points: &Vec<BookPlotPointsTable> = &complete_book.plot_points;
    let server_incidents: &Vec<BookIncidentsTable> = &complete_book.incidents;
    let server_chapter_contents: &Vec<BookChapterContentTable> = &complete_book.chapter_contents;
    let server_chapter_infos: &Vec<BookChapterInfosTable> = &complete_book.chapter_infos;
    let server_characters: &Vec<BookCharactersTable> = &complete_book.characters;
    let server_character_attributes: &Vec<BookCharactersAttributesTable> = &complete_book.character_attributes;
    let server_locations: &Vec<BookLocationTable> = &complete_book.locations;
    let server_location_elements: &Vec<LocationElementTable> = &complete_book.location_elements;
    let server_location_sub_elements: &Vec<LocationSubElementTable> = &complete_book.location_sub_elements;
    let server_worlds: &Vec<BookWorldTable> = &complete_book.worlds;
    let server_world_elements: &Vec<BookWorldElementsTable> = &complete_book.world_elements;
    let server_issues: &Vec<BookIssuesTable> = &complete_book.issues;
    let server_guide_lines: &Vec<BookGuideLineTable> = &complete_book.guide_line;
    let server_ai_guide_lines: &Vec<BookAIGuideLineTable> = &complete_book.ai_guide_line;

    let book_id: String = match complete_book.erit_books.first() {
        Some(book) => book.book_id.clone(),
        None => return Ok(false),
    };

    if !server_chapters.is_empty() {
        for server_chapter in server_chapters {
            let chapter_exists: bool = chapter_repo::is_chapter_exist(conn, user_id, &server_chapter.chapter_id, lang);
            let encrypted_title: String = encrypt_data_with_user_key(&server_chapter.title, &user_encryption_key)?;
            if chapter_exists {
                let update_successful: bool = chapter_repo::update_chapter(conn, user_id, &server_chapter.chapter_id, &encrypted_title, &server_chapter.hashed_title, server_chapter.chapter_order, server_chapter.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = chapter_repo::insert_sync_chapter(conn, &server_chapter.chapter_id, &server_chapter.book_id, user_id, &encrypted_title, Some(&server_chapter.hashed_title), Some(0), Some(server_chapter.chapter_order), server_chapter.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_act_summaries.is_empty() {
        for server_act_summary in server_act_summaries {
            let act_summary_exists: bool = act_repo::act_summarize_exist(conn, user_id, &book_id, server_act_summary.act_index, lang)?;
            let encrypted_summary: String = encrypt_data_with_user_key(if let Some(ref s) = server_act_summary.summary { s } else { "" }, &user_encryption_key)?;
            if act_summary_exists {
                let update_successful: bool = act_repo::update_act_summary(conn, user_id, &book_id, server_act_summary.act_index, &encrypted_summary, server_act_summary.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let _insert_result: String = act_repo::insert_act_summary(conn, &server_act_summary.act_sum_id, user_id, &book_id, server_act_summary.act_index, &encrypted_summary, server_act_summary.last_update, lang)?;
            }
        }
    }

    if !server_plot_points.is_empty() {
        for server_plot_point in server_plot_points {
            let encrypted_title: String = encrypt_data_with_user_key(&server_plot_point.title, &user_encryption_key)?;
            let encrypted_summary: String = encrypt_data_with_user_key(if let Some(ref summary) = server_plot_point.summary { summary } else { "" }, &user_encryption_key)?;
            let plot_point_exists: bool = plotpoint_repo::plot_point_exist(conn, user_id, &book_id, &server_plot_point.plot_point_id, lang)?;
            if plot_point_exists {
                let update_successful: bool = plotpoint_repo::update_plot_point(conn, user_id, &book_id, &server_plot_point.plot_point_id, &encrypted_title, &server_plot_point.hashed_title, &encrypted_summary, server_plot_point.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = plotpoint_repo::insert_sync_plot_point(conn, &server_plot_point.plot_point_id, &encrypted_title, &server_plot_point.hashed_title, Some(&encrypted_summary), server_plot_point.linked_incident_id.as_deref(), user_id, &server_plot_point.book_id, server_plot_point.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_incidents.is_empty() {
        for server_incident in server_incidents {
            let encrypted_title: String = encrypt_data_with_user_key(&server_incident.title, &user_encryption_key)?;
            let encrypted_summary: String = encrypt_data_with_user_key(if let Some(ref summary) = server_incident.summary { summary } else { "" }, &user_encryption_key)?;
            let incident_exists: bool = incident_repo::incident_exist(conn, user_id, &book_id, &server_incident.incident_id, lang)?;
            if incident_exists {
                let update_successful: bool = incident_repo::update_incident(conn, user_id, &book_id, &server_incident.incident_id, &encrypted_title, &server_incident.hashed_title, &encrypted_summary, server_incident.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = incident_repo::insert_sync_incident(conn, &server_incident.incident_id, user_id, &server_incident.book_id, &encrypted_title, &server_incident.hashed_title, Some(&encrypted_summary), server_incident.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_chapter_contents.is_empty() {
        for server_chapter_content in server_chapter_contents {
            let chapter_content_exists: bool = chapter_content_repo::is_chapter_content_exist(conn, user_id, &server_chapter_content.content_id, lang)?;
            let content_str: String = server_chapter_content.content.as_ref().map(|v| serde_json::to_string(v).unwrap_or_default()).unwrap_or_default();
            let encrypted_content: String = encrypt_data_with_user_key(&content_str, &user_encryption_key)?;
            let words_count: i64 = server_chapter_content.words_count.unwrap_or(0);
            let time_on_it: i64 = server_chapter_content.time_on_it.unwrap_or(0);
            if chapter_content_exists {
                let update_successful: bool = chapter_content_repo::update_chapter_content(conn, user_id, &server_chapter_content.chapter_id, server_chapter_content.version, &encrypted_content, words_count, server_chapter_content.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = chapter_content_repo::insert_sync_chapter_content(conn, &server_chapter_content.content_id, &server_chapter_content.chapter_id, user_id, server_chapter_content.version, Some(&encrypted_content), words_count, time_on_it, server_chapter_content.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_chapter_infos.is_empty() {
        for server_chapter_info in server_chapter_infos {
            let chapter_info_exists: bool = chapter_repo::is_chapter_info_exist(conn, user_id, &server_chapter_info.chapter_id, lang);
            let encrypted_summary: String = encrypt_data_with_user_key(if let Some(ref summary) = server_chapter_info.summary { summary } else { "" }, &user_encryption_key)?;
            let encrypted_goal: String = encrypt_data_with_user_key(if let Some(ref goal) = server_chapter_info.goal { goal } else { "" }, &user_encryption_key)?;
            if chapter_info_exists {
                let update_successful: bool = chapter_repo::update_chapter_infos(conn, user_id, &server_chapter_info.chapter_id, server_chapter_info.act_id.unwrap_or(0), &server_chapter_info.book_id, server_chapter_info.incident_id.as_deref(), server_chapter_info.plot_point_id.as_deref(), &encrypted_summary, Some(&encrypted_goal), server_chapter_info.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = chapter_repo::insert_sync_chapter_info(conn, &server_chapter_info.chapter_info_id, &server_chapter_info.chapter_id, server_chapter_info.act_id, server_chapter_info.incident_id.as_deref(), server_chapter_info.plot_point_id.as_deref(), &server_chapter_info.book_id, user_id, Some(&encrypted_summary), Some(&encrypted_goal), server_chapter_info.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_characters.is_empty() {
        for server_character in server_characters {
            let character_exists: bool = character_repo::is_character_exist(conn, user_id, &server_character.character_id, lang)?;
            let character_data = character_repo::SyncCharacterData {
                first_name: encrypt_data_with_user_key(&server_character.first_name, &user_encryption_key)?,
                last_name: Some(encrypt_data_with_user_key(if let Some(ref last_name) = server_character.last_name { last_name } else { "" }, &user_encryption_key)?),
                nickname: Some(encrypt_data_with_user_key(if let Some(ref nickname) = server_character.nickname { nickname } else { "" }, &user_encryption_key)?),
                age: Some(encrypt_data_with_user_key(if let Some(ref age) = server_character.age { age } else { "" }, &user_encryption_key)?),
                gender: Some(encrypt_data_with_user_key(if let Some(ref gender) = server_character.gender { gender } else { "" }, &user_encryption_key)?),
                species: Some(encrypt_data_with_user_key(if let Some(ref species) = server_character.species { species } else { "" }, &user_encryption_key)?),
                nationality: Some(encrypt_data_with_user_key(if let Some(ref nationality) = server_character.nationality { nationality } else { "" }, &user_encryption_key)?),
                status: Some(encrypt_data_with_user_key(if let Some(ref status) = server_character.status { status } else { "alive" }, &user_encryption_key)?),
                category: encrypt_data_with_user_key(&server_character.category, &user_encryption_key)?,
                title: Some(encrypt_data_with_user_key(if let Some(ref title) = server_character.title { title } else { "" }, &user_encryption_key)?),
                image: Some(encrypt_data_with_user_key(if let Some(ref image) = server_character.image { image } else { "" }, &user_encryption_key)?),
                role: Some(encrypt_data_with_user_key(if let Some(ref role) = server_character.role { role } else { "" }, &user_encryption_key)?),
                biography: Some(encrypt_data_with_user_key(if let Some(ref biography) = server_character.biography { biography } else { "" }, &user_encryption_key)?),
                history: Some(encrypt_data_with_user_key(if let Some(ref history) = server_character.history { history } else { "" }, &user_encryption_key)?),
                speech_pattern: Some(encrypt_data_with_user_key(if let Some(ref speech_pattern) = server_character.speech_pattern { speech_pattern } else { "" }, &user_encryption_key)?),
                catchphrase: Some(encrypt_data_with_user_key(if let Some(ref catchphrase) = server_character.catchphrase { catchphrase } else { "" }, &user_encryption_key)?),
                residence: Some(encrypt_data_with_user_key(if let Some(ref residence) = server_character.residence { residence } else { "" }, &user_encryption_key)?),
                notes: Some(encrypt_data_with_user_key(if let Some(ref notes) = server_character.notes { notes } else { "" }, &user_encryption_key)?),
                color: Some(encrypt_data_with_user_key(if let Some(ref color) = server_character.color { color } else { "" }, &user_encryption_key)?),
            };
            if character_exists {
                let update_successful: bool = character_repo::update_character(conn, user_id, &server_character.character_id, &character_repo::CharacterData { first_name: character_data.first_name, last_name: character_data.last_name, nickname: character_data.nickname, age: character_data.age, gender: character_data.gender, species: character_data.species, nationality: character_data.nationality, status: character_data.status, title: character_data.title, category: Some(character_data.category), image: character_data.image, role: character_data.role, biography: character_data.biography, history: character_data.history, speech_pattern: character_data.speech_pattern, catchphrase: character_data.catchphrase, residence: character_data.residence, notes: character_data.notes, color: character_data.color }, server_character.last_update, lang, None)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = character_repo::insert_sync_character(conn, &server_character.character_id, &book_id, user_id, &character_data, server_character.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_character_attributes.is_empty() {
        for server_character_attribute in server_character_attributes {
            let character_attribute_exists: bool = character_repo::is_character_attribute_exist(conn, user_id, &server_character_attribute.attr_id, lang)?;
            let encrypted_attribute_name: String = encrypt_data_with_user_key(&server_character_attribute.attribute_name, &user_encryption_key)?;
            let encrypted_attribute_value: String = encrypt_data_with_user_key(&server_character_attribute.attribute_value, &user_encryption_key)?;
            if character_attribute_exists {
                let update_successful: bool = character_repo::update_character_attribute(conn, user_id, &server_character_attribute.attr_id, &encrypted_attribute_name, &encrypted_attribute_value, server_character_attribute.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = character_repo::insert_sync_character_attribute(conn, &server_character_attribute.attr_id, &server_character_attribute.character_id, user_id, &encrypted_attribute_name, &encrypted_attribute_value, server_character_attribute.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_locations.is_empty() {
        for server_location in server_locations {
            let location_exists: bool = location_repo::is_location_exist(conn, user_id, &server_location.loc_id, lang)?;
            let encrypted_location_name: String = encrypt_data_with_user_key(&server_location.loc_name, &user_encryption_key)?;
            if location_exists {
                let update_successful: bool = location_repo::update_location_section(conn, user_id, &server_location.loc_id, &encrypted_location_name, &server_location.loc_original_name, server_location.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = location_repo::insert_sync_location(conn, &server_location.loc_id, &book_id, user_id, &encrypted_location_name, &server_location.loc_original_name, server_location.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_location_elements.is_empty() {
        for server_location_element in server_location_elements {
            let location_element_exists: bool = location_repo::is_location_element_exist(conn, user_id, &server_location_element.element_id, lang)?;
            let encrypted_element_name: String = encrypt_data_with_user_key(&server_location_element.element_name, &user_encryption_key)?;
            let encrypted_element_description: String = encrypt_data_with_user_key(if let Some(ref element_description) = server_location_element.element_description { element_description } else { "" }, &user_encryption_key)?;
            if location_element_exists {
                let update_successful: bool = location_repo::update_location_element(conn, user_id, &server_location_element.element_id, &encrypted_element_name, &server_location_element.original_name, &encrypted_element_description, server_location_element.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = location_repo::insert_sync_location_element(conn, &server_location_element.element_id, &server_location_element.location, user_id, &encrypted_element_name, &server_location_element.original_name, Some(&encrypted_element_description), server_location_element.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_location_sub_elements.is_empty() {
        for server_location_sub_element in server_location_sub_elements {
            let location_sub_element_exists: bool = location_repo::is_location_sub_element_exist(conn, user_id, &server_location_sub_element.sub_element_id, lang)?;
            let encrypted_sub_element_name: String = encrypt_data_with_user_key(&server_location_sub_element.sub_elem_name, &user_encryption_key)?;
            let encrypted_sub_element_description: String = encrypt_data_with_user_key(if let Some(ref sub_elem_description) = server_location_sub_element.sub_elem_description { sub_elem_description } else { "" }, &user_encryption_key)?;
            if location_sub_element_exists {
                let update_successful: bool = location_repo::update_location_sub_element(conn, user_id, &server_location_sub_element.sub_element_id, &encrypted_sub_element_name, &server_location_sub_element.original_name, &encrypted_sub_element_description, server_location_sub_element.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = location_repo::insert_sync_location_sub_element(conn, &server_location_sub_element.sub_element_id, &server_location_sub_element.element_id, user_id, &encrypted_sub_element_name, &server_location_sub_element.original_name, Some(&encrypted_sub_element_description), server_location_sub_element.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_worlds.is_empty() {
        for server_world in server_worlds {
            let world_exists: bool = world_repo::world_exist(conn, user_id, &book_id, &server_world.world_id, lang)?;
            let encrypted_name: String = encrypt_data_with_user_key(&server_world.name, &user_encryption_key)?;
            let encrypted_history: String = encrypt_data_with_user_key(if let Some(ref history) = server_world.history { history } else { "" }, &user_encryption_key)?;
            let encrypted_politics: String = encrypt_data_with_user_key(if let Some(ref politics) = server_world.politics { politics } else { "" }, &user_encryption_key)?;
            let encrypted_economy: String = encrypt_data_with_user_key(if let Some(ref economy) = server_world.economy { economy } else { "" }, &user_encryption_key)?;
            let encrypted_religion: String = encrypt_data_with_user_key(if let Some(ref religion) = server_world.religion { religion } else { "" }, &user_encryption_key)?;
            let encrypted_languages: String = encrypt_data_with_user_key(if let Some(ref languages) = server_world.languages { languages } else { "" }, &user_encryption_key)?;
            if world_exists {
                let update_successful: bool = world_repo::update_world(conn, user_id, &server_world.world_id, &encrypted_name, &server_world.hashed_name, &encrypted_history, &encrypted_politics, &encrypted_economy, &encrypted_religion, &encrypted_languages, server_world.last_update, lang, None)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = world_repo::insert_sync_world(conn, &server_world.world_id, &encrypted_name, &server_world.hashed_name, user_id, &book_id, Some(&encrypted_history), Some(&encrypted_politics), Some(&encrypted_economy), Some(&encrypted_religion), Some(&encrypted_languages), server_world.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_world_elements.is_empty() {
        for server_world_element in server_world_elements {
            let world_element_exists: bool = world_repo::world_element_exist(conn, user_id, &server_world_element.world_id, &server_world_element.element_id, lang)?;
            let encrypted_name: String = encrypt_data_with_user_key(&server_world_element.name, &user_encryption_key)?;
            let encrypted_description: String = encrypt_data_with_user_key(if let Some(ref description) = server_world_element.description { description } else { "" }, &user_encryption_key)?;
            if world_element_exists {
                let update_successful: bool = world_repo::update_world_element(conn, user_id, &server_world_element.element_id, &encrypted_name, &encrypted_description, server_world_element.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = world_repo::insert_sync_world_element(conn, &server_world_element.element_id, &server_world_element.world_id, user_id, server_world_element.element_type, &encrypted_name, &server_world_element.original_name, Some(&encrypted_description), server_world_element.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_issues.is_empty() {
        for server_issue in server_issues {
            let issue_exists: bool = issue_repo::issue_exist(conn, user_id, &book_id, &server_issue.issue_id, lang)?;
            let encrypted_name: String = encrypt_data_with_user_key(&server_issue.name, &user_encryption_key)?;
            if issue_exists {
                let update_successful: bool = issue_repo::update_issue(conn, user_id, &book_id, &server_issue.issue_id, &encrypted_name, &server_issue.hashed_issue_name, server_issue.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = issue_repo::insert_sync_issue(conn, &server_issue.issue_id, user_id, &server_issue.book_id, &encrypted_name, &server_issue.hashed_issue_name, server_issue.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_guide_lines.is_empty() {
        for server_guide_line in server_guide_lines {
            let guide_line_exists: bool = guideline_repo::guide_line_exist(conn, user_id, &book_id, lang)?;
            let encrypted_tone: Option<String> = if let Some(ref tone) = server_guide_line.tone { Some(encrypt_data_with_user_key(tone, &user_encryption_key)?) } else { None };
            let encrypted_atmosphere: Option<String> = if let Some(ref atmosphere) = server_guide_line.atmosphere { Some(encrypt_data_with_user_key(atmosphere, &user_encryption_key)?) } else { None };
            let encrypted_writing_style: Option<String> = if let Some(ref writing_style) = server_guide_line.writing_style { Some(encrypt_data_with_user_key(writing_style, &user_encryption_key)?) } else { None };
            let encrypted_themes: Option<String> = if let Some(ref themes) = server_guide_line.themes { Some(encrypt_data_with_user_key(themes, &user_encryption_key)?) } else { None };
            let encrypted_symbolism: Option<String> = if let Some(ref symbolism) = server_guide_line.symbolism { Some(encrypt_data_with_user_key(symbolism, &user_encryption_key)?) } else { None };
            let encrypted_motifs: Option<String> = if let Some(ref motifs) = server_guide_line.motifs { Some(encrypt_data_with_user_key(motifs, &user_encryption_key)?) } else { None };
            let encrypted_narrative_voice: Option<String> = if let Some(ref narrative_voice) = server_guide_line.narrative_voice { Some(encrypt_data_with_user_key(narrative_voice, &user_encryption_key)?) } else { None };
            let encrypted_pacing: Option<String> = if let Some(ref pacing) = server_guide_line.pacing { Some(encrypt_data_with_user_key(pacing, &user_encryption_key)?) } else { None };
            let encrypted_key_messages: Option<String> = if let Some(ref key_messages) = server_guide_line.key_messages { Some(encrypt_data_with_user_key(key_messages, &user_encryption_key)?) } else { None };
            let encrypted_intended_audience: Option<String> = if let Some(ref intended_audience) = server_guide_line.intended_audience { Some(encrypt_data_with_user_key(intended_audience, &user_encryption_key)?) } else { None };
            if guide_line_exists {
                let update_successful: bool = guideline_repo::update_guide_line(conn, user_id, &book_id, encrypted_tone.as_deref(), encrypted_atmosphere.as_deref(), encrypted_writing_style.as_deref(), encrypted_themes.as_deref(), encrypted_symbolism.as_deref(), encrypted_motifs.as_deref(), encrypted_narrative_voice.as_deref(), encrypted_pacing.as_deref(), encrypted_key_messages.as_deref(), encrypted_intended_audience.as_deref(), server_guide_line.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = guideline_repo::insert_sync_guide_line(conn, user_id, &book_id, encrypted_tone.as_deref(), encrypted_atmosphere.as_deref(), encrypted_writing_style.as_deref(), encrypted_themes.as_deref(), encrypted_symbolism.as_deref(), encrypted_motifs.as_deref(), encrypted_narrative_voice.as_deref(), encrypted_pacing.as_deref(), encrypted_intended_audience.as_deref(), encrypted_key_messages.as_deref(), server_guide_line.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !server_ai_guide_lines.is_empty() {
        for server_ai_guide_line in server_ai_guide_lines {
            let ai_guide_line_exists: bool = guideline_repo::ai_guide_line_exist(conn, user_id, &book_id, lang)?;
            let encrypted_global_resume: Option<String> = if let Some(ref global_resume) = server_ai_guide_line.global_resume { Some(encrypt_data_with_user_key(global_resume, &user_encryption_key)?) } else { None };
            let encrypted_themes: Option<String> = if let Some(ref themes) = server_ai_guide_line.themes { Some(encrypt_data_with_user_key(themes, &user_encryption_key)?) } else { None };
            let encrypted_tone: Option<String> = if let Some(ref tone) = server_ai_guide_line.tone { Some(encrypt_data_with_user_key(tone, &user_encryption_key)?) } else { None };
            let encrypted_atmosphere: Option<String> = if let Some(ref atmosphere) = server_ai_guide_line.atmosphere { Some(encrypt_data_with_user_key(atmosphere, &user_encryption_key)?) } else { None };
            let encrypted_current_resume: Option<String> = if let Some(ref current_resume) = server_ai_guide_line.current_resume { Some(encrypt_data_with_user_key(current_resume, &user_encryption_key)?) } else { None };
            if ai_guide_line_exists {
                let update_successful: bool = guideline_repo::insert_ai_guide_line(conn, user_id, &book_id, server_ai_guide_line.narrative_type, server_ai_guide_line.dialogue_type, encrypted_global_resume.as_deref(), encrypted_atmosphere.as_deref(), server_ai_guide_line.verbe_tense, server_ai_guide_line.langue, encrypted_themes.as_deref(), server_ai_guide_line.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = guideline_repo::insert_sync_ai_guide_line(conn, user_id, &book_id, encrypted_global_resume.as_deref(), encrypted_themes.as_deref(), server_ai_guide_line.verbe_tense, server_ai_guide_line.narrative_type, server_ai_guide_line.langue, server_ai_guide_line.dialogue_type, encrypted_tone.as_deref(), encrypted_atmosphere.as_deref(), encrypted_current_resume.as_deref(), server_ai_guide_line.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !complete_book.book_tools.is_empty() {
        for server_book_tool in &complete_book.book_tools {
            let success: bool = book_repo::insert_sync_book_tools(conn, &book_id, user_id, server_book_tool.characters_enabled, server_book_tool.worlds_enabled, server_book_tool.locations_enabled, server_book_tool.spells_enabled, server_book_tool.last_update, lang);
            if !success { return Ok(false); }
        }
    }

    if !complete_book.spell_tags.is_empty() {
        for server_spell_tag in &complete_book.spell_tags {
            let spell_tag_exists: bool = spell_tag_repo::is_spell_tag_exist(conn, user_id, &server_spell_tag.tag_id, lang)?;
            let encrypted_name: String = encrypt_data_with_user_key(&server_spell_tag.name, &user_encryption_key)?;
            if spell_tag_exists {
                let update_successful: bool = spell_tag_repo::update_sync_spell_tag(conn, user_id, &server_spell_tag.tag_id, &encrypted_name, &server_spell_tag.name_hash, server_spell_tag.color.as_deref(), server_spell_tag.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = spell_tag_repo::insert_sync_spell_tag(conn, &server_spell_tag.tag_id, &server_spell_tag.book_id, user_id, &encrypted_name, &server_spell_tag.name_hash, server_spell_tag.color.as_deref(), server_spell_tag.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    if !complete_book.spells.is_empty() {
        for server_spell in &complete_book.spells {
            let spell_exists: bool = spell_repo::is_spell_exist(conn, user_id, &server_spell.spell_id, lang)?;
            let encrypted_name: String = encrypt_data_with_user_key(&server_spell.name, &user_encryption_key)?;
            let encrypted_description: Option<String> = if let Some(ref desc) = server_spell.description { Some(encrypt_data_with_user_key(desc, &user_encryption_key)?) } else { None };
            let encrypted_appearance: Option<String> = if let Some(ref app) = server_spell.appearance { Some(encrypt_data_with_user_key(app, &user_encryption_key)?) } else { None };
            let encrypted_tags: Option<String> = if let Some(ref tags) = server_spell.tags { Some(encrypt_data_with_user_key(tags, &user_encryption_key)?) } else { None };
            let encrypted_power_level: Option<String> = if let Some(ref power_level) = server_spell.power_level { Some(encrypt_data_with_user_key(power_level, &user_encryption_key)?) } else { None };
            let encrypted_components: Option<String> = if let Some(ref components) = server_spell.components { Some(encrypt_data_with_user_key(components, &user_encryption_key)?) } else { None };
            let encrypted_limitations: Option<String> = if let Some(ref limitations) = server_spell.limitations { Some(encrypt_data_with_user_key(limitations, &user_encryption_key)?) } else { None };
            let encrypted_notes: Option<String> = if let Some(ref notes) = server_spell.notes { Some(encrypt_data_with_user_key(notes, &user_encryption_key)?) } else { None };
            if spell_exists {
                let update_successful: bool = spell_repo::update_sync_spell(conn, user_id, &server_spell.spell_id, &encrypted_name, &server_spell.name_hash, encrypted_description.as_deref(), encrypted_appearance.as_deref(), encrypted_tags.as_deref(), encrypted_power_level.as_deref(), encrypted_components.as_deref(), encrypted_limitations.as_deref(), encrypted_notes.as_deref(), server_spell.last_update, lang)?;
                if !update_successful { return Ok(false); }
            } else {
                let insert_successful: bool = spell_repo::insert_sync_spell(conn, &server_spell.spell_id, &server_spell.book_id, user_id, &encrypted_name, &server_spell.name_hash, encrypted_description.as_deref(), encrypted_appearance.as_deref(), encrypted_tags.as_deref(), encrypted_power_level.as_deref(), encrypted_components.as_deref(), encrypted_limitations.as_deref(), encrypted_notes.as_deref(), server_spell.last_update, lang)?;
                if !insert_successful { return Ok(false); }
            }
        }
    }

    Ok(true)
}

/// Retrieves all synced books for a user with their complete hierarchical data structure.
/// Fetches all related entities (chapters, characters, locations, etc.) and organizes them by book.
/// * `conn` - Database connection
/// * `user_id` - The unique identifier of the user
/// * `lang` - The language for error messages
/// Returns an array of SyncedBookFull objects with decrypted data.
pub fn get_synced_books(conn: &Connection, user_id: &str, lang: Lang) -> AppResult<Vec<SyncedBookFull>> {
    let user_encryption_key: String = get_user_encryption_key(user_id)?;

    let all_books: Vec<book_repo::SyncedBookResult> = book_repo::fetch_synced_books(conn, user_id, lang)?;
    let all_chapters: Vec<chapter_repo::SyncedChapterResult> = chapter_repo::fetch_synced_chapters(conn, user_id, lang)?;
    let all_chapter_contents: Vec<chapter_content_repo::SyncedChapterContentResult> = chapter_content_repo::fetch_synced_chapter_contents(conn, user_id, lang)?;
    let all_chapter_infos: Vec<chapter_repo::SyncedChapterInfoResult> = chapter_repo::fetch_synced_chapter_infos(conn, user_id, lang)?;
    let all_characters: Vec<character_repo::SyncedCharacterResult> = character_repo::fetch_synced_characters(conn, user_id, lang)?;
    let all_character_attributes: Vec<character_repo::SyncedCharacterAttributeResult> = character_repo::fetch_synced_character_attributes(conn, user_id, lang)?;
    let all_locations: Vec<location_repo::SyncedLocationResult> = location_repo::fetch_synced_locations(conn, user_id, lang)?;
    let all_location_elements: Vec<location_repo::SyncedLocationElementResult> = location_repo::fetch_synced_location_elements(conn, user_id, lang)?;
    let all_location_sub_elements: Vec<location_repo::SyncedLocationSubElementResult> = location_repo::fetch_synced_location_sub_elements(conn, user_id, lang)?;
    let all_worlds: Vec<world_repo::SyncedWorldResult> = world_repo::fetch_synced_worlds(conn, user_id, lang)?;
    let all_world_elements: Vec<world_repo::SyncedWorldElementResult> = world_repo::fetch_synced_world_elements(conn, user_id, lang)?;
    let all_incidents: Vec<incident_repo::SyncedIncidentResult> = incident_repo::fetch_synced_incidents(conn, user_id, lang)?;
    let all_plot_points: Vec<plotpoint_repo::SyncedPlotPointResult> = plotpoint_repo::fetch_synced_plot_points(conn, user_id, lang)?;
    let all_issues: Vec<issue_repo::SyncedIssueResult> = issue_repo::fetch_synced_issues(conn, user_id, lang)?;
    let all_act_summaries: Vec<act_repo::SyncedActSummaryResult> = act_repo::fetch_synced_act_summaries(conn, user_id, lang)?;
    let all_guidelines: Vec<guideline_repo::SyncedGuideLineResult> = guideline_repo::fetch_synced_guide_line(conn, user_id, lang)?;
    let all_ai_guidelines: Vec<guideline_repo::SyncedAIGuideLineResult> = guideline_repo::fetch_synced_ai_guide_line(conn, user_id, lang)?;
    let all_spells: Vec<spell_repo::SyncedSpellResult> = spell_repo::fetch_synced_spells(conn, user_id, lang)?;
    let all_spell_tags: Vec<spell_tag_repo::SyncedSpellTagResult> = spell_tag_repo::fetch_synced_spell_tags(conn, user_id, lang)?;

    let mut synced_books: Vec<SyncedBookFull> = Vec::with_capacity(all_books.len());

    for book_record in &all_books {
        let current_book_id: &str = &book_record.book_id;

        let book_chapters: Vec<SyncedChapterFull> = all_chapters.iter()
            .filter(|chapter_record| chapter_record.book_id == current_book_id)
            .map(|chapter_record| {
                let current_chapter_id: &str = &chapter_record.chapter_id;

                let chapter_contents: Vec<SyncedChapterContent> = all_chapter_contents.iter()
                    .filter(|content_record| content_record.chapter_id == current_chapter_id)
                    .map(|content_record| SyncedChapterContent { id: content_record.content_id.clone(), last_update: content_record.last_update })
                    .collect();

                let chapter_info: Option<SyncedChapterInfo> = all_chapter_infos.iter()
                    .find(|info_record| info_record.chapter_id.as_deref() == Some(current_chapter_id))
                    .map(|info_record| SyncedChapterInfo { id: info_record.chapter_info_id.clone(), last_update: info_record.last_update });

                SyncedChapterFull {
                    id: current_chapter_id.to_string(),
                    name: decrypt_data_with_user_key(&chapter_record.title, &user_encryption_key).unwrap_or_default(),
                    last_update: chapter_record.last_update,
                    contents: chapter_contents,
                    info: chapter_info,
                }
            })
            .collect();

        let book_characters: Vec<SyncedCharacterFull> = all_characters.iter()
            .filter(|character_record| character_record.book_id == current_book_id)
            .map(|character_record| {
                let current_character_id: &str = &character_record.character_id;

                let character_attributes: Vec<SyncedCharacterAttribute> = all_character_attributes.iter()
                    .filter(|attribute_record| attribute_record.character_id == current_character_id)
                    .map(|attribute_record| SyncedCharacterAttribute {
                        id: attribute_record.attr_id.clone(),
                        name: decrypt_data_with_user_key(&attribute_record.attribute_name, &user_encryption_key).unwrap_or_default(),
                        last_update: attribute_record.last_update,
                    })
                    .collect();

                SyncedCharacterFull {
                    id: current_character_id.to_string(),
                    name: decrypt_data_with_user_key(&character_record.first_name, &user_encryption_key).unwrap_or_default(),
                    last_update: character_record.last_update,
                    attributes: character_attributes,
                }
            })
            .collect();

        let book_locations: Vec<SyncedLocationFull> = all_locations.iter()
            .filter(|location_record| location_record.book_id == current_book_id)
            .map(|location_record| {
                let current_location_id: &str = &location_record.loc_id;

                let location_elements: Vec<SyncedLocationElement> = all_location_elements.iter()
                    .filter(|element_record| element_record.location == current_location_id)
                    .map(|element_record| {
                        let current_element_id: &str = &element_record.element_id;

                        let location_sub_elements: Vec<SyncedLocationSubElement> = all_location_sub_elements.iter()
                            .filter(|sub_element_record| sub_element_record.element_id == current_element_id)
                            .map(|sub_element_record| SyncedLocationSubElement {
                                id: sub_element_record.sub_element_id.clone(),
                                name: decrypt_data_with_user_key(&sub_element_record.sub_elem_name, &user_encryption_key).unwrap_or_default(),
                                last_update: sub_element_record.last_update,
                            })
                            .collect();

                        SyncedLocationElement {
                            id: current_element_id.to_string(),
                            name: decrypt_data_with_user_key(&element_record.element_name, &user_encryption_key).unwrap_or_default(),
                            last_update: element_record.last_update,
                            sub_elements: location_sub_elements,
                        }
                    })
                    .collect();

                SyncedLocationFull {
                    id: current_location_id.to_string(),
                    name: decrypt_data_with_user_key(&location_record.loc_name, &user_encryption_key).unwrap_or_default(),
                    last_update: location_record.last_update,
                    elements: location_elements,
                }
            })
            .collect();

        let book_worlds: Vec<SyncedWorldFull> = all_worlds.iter()
            .filter(|world_record| world_record.book_id == current_book_id)
            .map(|world_record| {
                let current_world_id: &str = &world_record.world_id;

                let world_elements: Vec<SyncedWorldElement> = all_world_elements.iter()
                    .filter(|world_element_record| world_element_record.world_id == current_world_id)
                    .map(|world_element_record| SyncedWorldElement {
                        id: world_element_record.element_id.clone(),
                        name: decrypt_data_with_user_key(&world_element_record.name, &user_encryption_key).unwrap_or_default(),
                        last_update: world_element_record.last_update,
                    })
                    .collect();

                SyncedWorldFull {
                    id: current_world_id.to_string(),
                    name: decrypt_data_with_user_key(&world_record.name, &user_encryption_key).unwrap_or_default(),
                    last_update: world_record.last_update,
                    elements: world_elements,
                }
            })
            .collect();

        let book_incidents: Vec<SyncedIncident> = all_incidents.iter()
            .filter(|incident_record| incident_record.book_id == current_book_id)
            .map(|incident_record| SyncedIncident { id: incident_record.incident_id.clone(), name: decrypt_data_with_user_key(&incident_record.title, &user_encryption_key).unwrap_or_default(), last_update: incident_record.last_update })
            .collect();

        let book_plot_points: Vec<SyncedPlotPoint> = all_plot_points.iter()
            .filter(|plot_point_record| plot_point_record.book_id == current_book_id)
            .map(|plot_point_record| SyncedPlotPoint { id: plot_point_record.plot_point_id.clone(), name: decrypt_data_with_user_key(&plot_point_record.title, &user_encryption_key).unwrap_or_default(), last_update: plot_point_record.last_update })
            .collect();

        let book_issues: Vec<SyncedIssue> = all_issues.iter()
            .filter(|issue_record| issue_record.book_id == current_book_id)
            .map(|issue_record| SyncedIssue { id: issue_record.issue_id.clone(), name: decrypt_data_with_user_key(&issue_record.name, &user_encryption_key).unwrap_or_default(), last_update: issue_record.last_update })
            .collect();

        let book_act_summaries: Vec<SyncedActSummary> = all_act_summaries.iter()
            .filter(|act_summary_record| act_summary_record.book_id == current_book_id)
            .map(|act_summary_record| SyncedActSummary { id: act_summary_record.act_sum_id.clone(), last_update: act_summary_record.last_update })
            .collect();

        let book_guide_line: Option<SyncedGuideLine> = all_guidelines.iter()
            .find(|guideline_item| guideline_item.book_id == current_book_id)
            .map(|guideline_record| SyncedGuideLine { last_update: guideline_record.last_update });

        let book_ai_guide_line: Option<SyncedAIGuideLine> = all_ai_guidelines.iter()
            .find(|ai_guideline_item| ai_guideline_item.book_id == current_book_id)
            .map(|ai_guideline_record| SyncedAIGuideLine { last_update: ai_guideline_record.last_update });

        let book_tools_query: AppResult<Option<book_repo::SyncedBookToolsResult>> = book_repo::fetch_synced_book_tools(conn, user_id, current_book_id, lang);
        let book_tools: Option<SyncedBookTools> = book_tools_query.ok().flatten().map(|book_tools_row| SyncedBookTools {
            last_update: book_tools_row.last_update,
            characters_enabled: book_tools_row.characters_enabled == 1,
            worlds_enabled: book_tools_row.worlds_enabled == 1,
            locations_enabled: book_tools_row.locations_enabled == 1,
            spells_enabled: book_tools_row.spells_enabled == 1,
        });

        let book_spells: Vec<SyncedSpell> = all_spells.iter()
            .filter(|spell_record| spell_record.book_id == current_book_id)
            .map(|spell_record| SyncedSpell { id: spell_record.spell_id.clone(), name: decrypt_data_with_user_key(&spell_record.name, &user_encryption_key).unwrap_or_default(), last_update: spell_record.last_update })
            .collect();

        let book_spell_tags: Vec<SyncedSpellTag> = all_spell_tags.iter()
            .filter(|spell_tag_record| spell_tag_record.book_id == current_book_id)
            .map(|spell_tag_record| SyncedSpellTag { id: spell_tag_record.tag_id.clone(), name: decrypt_data_with_user_key(&spell_tag_record.name, &user_encryption_key).unwrap_or_default(), last_update: spell_tag_record.last_update })
            .collect();

        synced_books.push(SyncedBookFull {
            id: current_book_id.to_string(),
            book_type: book_record.book_type.clone(),
            title: decrypt_data_with_user_key(&book_record.title, &user_encryption_key).unwrap_or_default(),
            sub_title: if let Some(ref sub_title) = book_record.sub_title { if sub_title.is_empty() { None } else { decrypt_data_with_user_key(sub_title, &user_encryption_key).ok() } } else { None },
            last_update: book_record.last_update,
            chapters: book_chapters,
            characters: book_characters,
            locations: book_locations,
            worlds: book_worlds,
            incidents: book_incidents,
            plot_points: book_plot_points,
            issues: book_issues,
            act_summaries: book_act_summaries,
            guide_line: book_guide_line,
            ai_guide_line: book_ai_guide_line,
            book_tools,
            spells: book_spells,
            spell_tags: book_spell_tags,
        });
    }

    Ok(synced_books)
}

/// Retrieves all series for the current user with lightweight structure for sync comparison.
/// Returns synced series with nested characters, worlds, locations, spells, and spell tags.
/// All encrypted fields are decrypted before return.
/// * `conn` - Database connection
/// * `user_id` - The unique identifier of the user
/// * `lang` - The language for error messages
/// Returns an array of synced series with all nested entities.
pub fn get_synced_series(conn: &Connection, user_id: &str, lang: Lang) -> AppResult<Vec<SyncedSeries>> {
    let user_encryption_key: String = get_user_encryption_key(user_id)?;

    let all_series: Vec<series_repo::SyncedSeriesResult> = series_repo::fetch_synced_series(conn, user_id, lang)?;
    let all_series_books: Vec<series_repo::SyncedSeriesBookResult> = series_repo::fetch_synced_series_books(conn, user_id, lang)?;
    let all_characters: Vec<series_character_repo::SyncedSeriesCharacterResult> = series_character_repo::fetch_synced_series_characters(conn, user_id, lang)?;
    let all_character_attributes: Vec<series_character_repo::SyncedSeriesCharacterAttributeResult> = series_character_repo::fetch_synced_series_character_attributes(conn, user_id, lang)?;
    let all_worlds: Vec<series_world_repo::SyncedSeriesWorldResult> = series_world_repo::fetch_synced_series_worlds(conn, user_id, lang)?;
    let all_world_elements: Vec<series_world_repo::SyncedSeriesWorldElementResult> = series_world_repo::fetch_synced_series_world_elements(conn, user_id, lang)?;
    let all_locations: Vec<series_location_repo::SyncedSeriesLocationResult> = series_location_repo::fetch_synced_series_locations(conn, user_id, lang)?;
    let all_location_elements: Vec<series_location_repo::SyncedSeriesLocationElementResult> = series_location_repo::fetch_synced_series_location_elements(conn, user_id, lang)?;
    let all_location_sub_elements: Vec<series_location_repo::SyncedSeriesLocationSubElementResult> = series_location_repo::fetch_synced_series_location_sub_elements(conn, user_id, lang)?;
    let all_spells: Vec<series_spell_repo::SyncedSeriesSpellResult> = series_spell_repo::fetch_synced_series_spells(conn, user_id, lang)?;
    let all_spell_tags: Vec<series_spell_repo::SyncedSeriesSpellTagResult> = series_spell_repo::fetch_synced_series_spell_tags(conn, user_id, lang)?;

    let mut synced_series_list: Vec<SyncedSeries> = Vec::with_capacity(all_series.len());

    for series in &all_series {
        let series_id: &str = &series.series_id;

        let books: Vec<SyncedSeriesBook> = all_series_books.iter()
            .filter(|sb| sb.series_id == series_id)
            .map(|sb| SyncedSeriesBook { book_id: sb.book_id.clone(), order: sb.book_order, last_update: sb.last_update })
            .collect();

        let characters: Vec<SyncedSeriesCharacter> = all_characters.iter()
            .filter(|c| c.series_id == series_id)
            .map(|c| SyncedSeriesCharacter {
                id: c.character_id.clone(),
                name: decrypt_data_with_user_key(&c.first_name, &user_encryption_key).unwrap_or_default(),
                last_update: c.last_update,
                attributes: all_character_attributes.iter()
                    .filter(|a| a.character_id == c.character_id)
                    .map(|a| SyncedSeriesCharacterAttribute {
                        id: a.attr_id.clone(),
                        name: decrypt_data_with_user_key(&a.attribute_name, &user_encryption_key).unwrap_or_default(),
                        last_update: a.last_update,
                    })
                    .collect(),
            })
            .collect();

        let worlds: Vec<SyncedSeriesWorld> = all_worlds.iter()
            .filter(|w| w.series_id == series_id)
            .map(|w| SyncedSeriesWorld {
                id: w.world_id.clone(),
                name: decrypt_data_with_user_key(&w.name, &user_encryption_key).unwrap_or_default(),
                last_update: w.last_update,
                elements: all_world_elements.iter()
                    .filter(|e| e.world_id == w.world_id)
                    .map(|e| SyncedSeriesWorldElement {
                        id: e.element_id.clone(),
                        name: decrypt_data_with_user_key(&e.name, &user_encryption_key).unwrap_or_default(),
                        last_update: e.last_update,
                    })
                    .collect(),
            })
            .collect();

        let locations: Vec<SyncedSeriesLocation> = all_locations.iter()
            .filter(|l| l.series_id == series_id)
            .map(|l| SyncedSeriesLocation {
                id: l.loc_id.clone(),
                name: decrypt_data_with_user_key(&l.loc_name, &user_encryption_key).unwrap_or_default(),
                last_update: l.last_update,
                elements: all_location_elements.iter()
                    .filter(|e| e.location_id == l.loc_id)
                    .map(|e| SyncedSeriesLocationElement {
                        id: e.element_id.clone(),
                        name: decrypt_data_with_user_key(&e.element_name, &user_encryption_key).unwrap_or_default(),
                        last_update: e.last_update,
                        sub_elements: all_location_sub_elements.iter()
                            .filter(|se| se.element_id == e.element_id)
                            .map(|se| SyncedSeriesLocationSubElement {
                                id: se.sub_element_id.clone(),
                                name: decrypt_data_with_user_key(&se.sub_elem_name, &user_encryption_key).unwrap_or_default(),
                                last_update: se.last_update,
                            })
                            .collect(),
                    })
                    .collect(),
            })
            .collect();

        let spells: Vec<SyncedSeriesSpell> = all_spells.iter()
            .filter(|s| s.series_id == series_id)
            .map(|s| SyncedSeriesSpell { id: s.spell_id.clone(), name: decrypt_data_with_user_key(&s.name, &user_encryption_key).unwrap_or_default(), last_update: s.last_update })
            .collect();

        let spell_tags: Vec<SyncedSeriesSpellTag> = all_spell_tags.iter()
            .filter(|t| t.series_id == series_id)
            .map(|t| SyncedSeriesSpellTag { id: t.tag_id.clone(), name: decrypt_data_with_user_key(&t.name, &user_encryption_key).unwrap_or_default(), last_update: t.last_update })
            .collect();

        synced_series_list.push(SyncedSeries {
            id: series_id.to_string(),
            name: decrypt_data_with_user_key(&series.name, &user_encryption_key).unwrap_or_default(),
            description: if let Some(ref description) = series.description { if description.is_empty() { None } else { decrypt_data_with_user_key(description, &user_encryption_key).ok() } } else { None },
            last_update: series.last_update,
            books,
            characters,
            worlds,
            locations,
            spells,
            spell_tags,
        });
    }

    Ok(synced_series_list)
}
