'use client'
import {useCallback, useContext, useEffect, useState} from 'react';
import {SeriesLocationItem, SeriesLocationElement, SeriesLocationSubElement} from '@/lib/models/Series';
import {SessionContext} from '@/context/SessionContext';
import {BookContext} from '@/context/BookContext';
import {AlertContext} from '@/context/AlertContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import System from '@/lib/models/System';
import {useTranslations} from 'next-intl';
import {ViewMode} from '@/shared/interface';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {LocalSyncQueueContext, LocalSyncQueueContextProps} from '@/context/SyncQueueContext';
import {BooksSyncContext, BooksSyncContextProps} from '@/context/BooksSyncContext';
import {SyncedBook} from '@/lib/models/SyncedBook';
import {SeriesContext, SeriesContextProps} from '@/context/SeriesContext';
import {SeriesSyncContext, SeriesSyncContextProps} from '@/context/SeriesSyncContext';
import {SyncedSeries} from '@/lib/models/SyncedSeries';

export interface SubElement {
    id: string;
    name: string;
    description: string;
}

export interface Element {
    id: string;
    name: string;
    description: string;
    subElements: SubElement[];
}

export interface LocationProps {
    id: string;
    name: string;
    elements: Element[];
    seriesLocationId?: string | null;
}

interface LocationListResponse {
    locations: LocationProps[];
    enabled: boolean;
}

export interface UseLocationsConfig {
    entityType: 'book' | 'series';
    entityId: string;
}

export interface UseLocationsReturn {
    // State
    sections: LocationProps[];
    seriesLocations: SeriesLocationItem[];
    toolEnabled: boolean;
    isLoading: boolean;
    isSeriesMode: boolean;
    bookSeriesId: string | null;
    newSectionName: string;
    newElementNames: { [key: string]: string };
    newSubElementNames: { [key: string]: string };

    // Navigation state
    viewMode: ViewMode;
    selectedSectionIndex: number;
    sectionsBackup: LocationProps[] | null;

    // Actions
    addSection: () => Promise<void>;
    addElement: (sectionId: string) => Promise<void>;
    addSubElement: (sectionId: string, elementIndex: number) => Promise<void>;
    removeSection: (sectionId: string) => Promise<void>;
    removeElement: (sectionId: string, elementIndex: number) => Promise<void>;
    removeSubElement: (sectionId: string, elementIndex: number, subElementIndex: number) => Promise<void>;
    updateElement: (sectionId: string, elementIndex: number, field: keyof Element, value: string) => void;
    updateSubElement: (sectionId: string, elementIndex: number, subElementIndex: number, field: keyof SubElement, value: string) => void;
    saveLocations: () => Promise<boolean>;
    toggleTool: (enabled: boolean) => Promise<void>;
    importFromSeries: (seriesLocationId: string) => Promise<void>;
    exportToSeries: (section: LocationProps) => Promise<void>;
    refreshLocations: () => Promise<void>;
    refreshSeriesLocations: () => Promise<void>;
    setNewSectionName: (name: string) => void;
    setNewElementNames: React.Dispatch<React.SetStateAction<{ [key: string]: string }>>;
    setNewSubElementNames: React.Dispatch<React.SetStateAction<{ [key: string]: string }>>;

    // Navigation actions
    enterDetailMode: (sectionIndex: number) => void;
    enterEditMode: () => void;
    exitEditMode: (save: boolean) => Promise<void>;
    backToList: () => void;
}

export function useLocations(config: UseLocationsConfig): UseLocationsReturn {
    const {entityType, entityId} = config;
    const t = useTranslations();
    const {lang} = useContext<LangContextProps>(LangContext);
    const {session} = useContext(SessionContext);
    const {book, setBook} = useContext(BookContext);
    const {errorMessage, successMessage} = useContext(AlertContext);
    const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
    const {addToQueue} = useContext<LocalSyncQueueContextProps>(LocalSyncQueueContext);
    const {localSyncedBooks} = useContext<BooksSyncContextProps>(BooksSyncContext);
    const {localSeries} = useContext<SeriesContextProps>(SeriesContext);
    const {localSyncedSeries} = useContext<SeriesSyncContextProps>(SeriesSyncContext);

    const [sections, setSections] = useState<LocationProps[]>([]);
    const [seriesLocations, setSeriesLocations] = useState<SeriesLocationItem[]>([]);
    const [toolEnabled, setToolEnabled] = useState<boolean>(entityType === 'series' || (book?.tools?.locations ?? false));
    const [isLoading, setIsLoading] = useState<boolean>(true);
    const [newSectionName, setNewSectionName] = useState<string>('');
    const [newElementNames, setNewElementNames] = useState<{ [key: string]: string }>({});
    const [newSubElementNames, setNewSubElementNames] = useState<{ [key: string]: string }>({});
    const [isAddingElement, setIsAddingElement] = useState<boolean>(false);
    const [isAddingSubElement, setIsAddingSubElement] = useState<boolean>(false);
    const [isAddingSection, setIsAddingSection] = useState<boolean>(false);

    // Navigation state
    const [viewMode, setViewMode] = useState<ViewMode>('list');
    const [selectedSectionIndex, setSelectedSectionIndex] = useState<number>(-1);
    const [sectionsBackup, setSectionsBackup] = useState<LocationProps[] | null>(null);

    const isSeriesMode: boolean = entityType === 'series';
    const bookSeriesId: string | null = book?.seriesId || null;
    const userToken: string = session?.accessToken || '';

    // Load locations on mount
    useEffect(function (): void {
        if (entityId) {
            refreshLocations();
        }
    }, [entityId]);

    // Load series locations for book mode
    useEffect(function (): void {
        if (bookSeriesId && !isSeriesMode) {
            refreshSeriesLocations();
        }
    }, [bookSeriesId, isSeriesMode]);

    const refreshSeriesLocations = useCallback(async function (): Promise<void> {
        if (!bookSeriesId) return;
        try {
            let response: SeriesLocationItem[];
            // Dual logic: offline ou livre local → IPC, sinon serveur
            if (isCurrentlyOffline() || book?.localBook) {
                response = await window.electron.invoke<SeriesLocationItem[]>(
                    'db:series:location:list',
                    {seriesId: bookSeriesId}
                );
            } else {
                response = await System.authGetQueryToServer<SeriesLocationItem[]>(
                    'series/location/list',
                    userToken,
                    lang,
                    {seriesid: bookSeriesId}
                );
            }
            if (response) {
                setSeriesLocations(response);
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                console.error('Error loading series locations:', e.message);
            }
        }
    }, [bookSeriesId, userToken, lang, isCurrentlyOffline, book?.localBook]);

    const refreshLocations = useCallback(async function (): Promise<void> {
        setIsLoading(true);
        try {
            if (isSeriesMode) {
                // Series mode - dual logic
                let response: SeriesLocationItem[];
                if (isCurrentlyOffline() || localSeries) {
                    response = await window.electron.invoke<SeriesLocationItem[]>(
                        'db:series:location:list',
                        {seriesId: entityId}
                    );
                } else {
                    response = await System.authGetQueryToServer<SeriesLocationItem[]>(
                        'series/location/list',
                        userToken,
                        lang,
                        {seriesid: entityId}
                    );
                }
                if (response) {
                    const mappedLocations: LocationProps[] = response.map(function (loc: SeriesLocationItem): LocationProps {
                        return {
                            id: loc.id,
                            name: loc.name,
                            elements: loc.elements.map(function (elem: SeriesLocationElement): Element {
                                return {
                                    id: elem.id,
                                    name: elem.name,
                                    description: elem.description,
                                    subElements: elem.subElements.map(function (sub: SeriesLocationSubElement): SubElement {
                                        return {
                                            id: sub.id,
                                            name: sub.name,
                                            description: sub.description,
                                        };
                                    }),
                                };
                            }),
                        };
                    });
                    setSections(mappedLocations);
                }
            } else {
                let response: LocationListResponse;
                if (isCurrentlyOffline()) {
                    response = await window.electron.invoke<LocationListResponse>('db:location:all', {bookid: entityId});
                } else if (book?.localBook) {
                    response = await window.electron.invoke<LocationListResponse>('db:location:all', {bookid: entityId});
                } else {
                    response = await System.authGetQueryToServer<LocationListResponse>(
                        'location/all',
                        userToken,
                        lang,
                        {bookid: entityId}
                    );
                }
                if (response) {
                    setSections(response.locations);
                    setToolEnabled(response.enabled);
                    if (setBook && book) {
                        setBook({
                            ...book,
                            tools: {
                                characters: book.tools?.characters ?? false,
                                worlds: book.tools?.worlds ?? false,
                                locations: response.enabled,
                                spells: book.tools?.spells ?? false
                            }
                        });
                    }
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownFetchLocations'));
            }
        } finally {
            setIsLoading(false);
        }
    }, [entityId, isSeriesMode, userToken, lang, book, setBook, errorMessage, t, isCurrentlyOffline]);

    const toggleTool = useCallback(async function (enabled: boolean): Promise<void> {
        if (isSeriesMode) return;
        try {
            const requestData = {
                bookId: book?.bookId,
                toolName: 'locations',
                enabled: enabled
            };
            let response: boolean;
            if (isCurrentlyOffline() || book?.localBook) {
                response = await window.electron.invoke<boolean>('db:book:tool:update', requestData);
            } else {
                response = await System.authPatchToServer<boolean>('book/tool-setting', requestData, userToken, lang);

                if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === book?.bookId)) {
                    addToQueue('db:book:tool:update', requestData);
                }
            }
            if (response && setBook && book) {
                setToolEnabled(enabled);
                setBook({
                    ...book,
                    tools: {
                        characters: book.tools?.characters ?? false,
                        worlds: book.tools?.worlds ?? false,
                        locations: enabled,
                        spells: book.tools?.spells ?? false
                    }
                });
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [isSeriesMode, book, setBook, userToken, lang, errorMessage, isCurrentlyOffline, addToQueue, localSyncedBooks]);

    const addSection = useCallback(async function (): Promise<void> {
        if (isAddingSection) return;
        if (!newSectionName.trim()) {
            errorMessage(t('locationComponent.errorSectionNameEmpty'));
            return;
        }
        setIsAddingSection(true);
        try {
            let sectionId: string;
            if (isSeriesMode) {
                // Series mode - dual logic
                const addData = {
                    seriesId: entityId,
                    name: newSectionName,
                };
                if (isCurrentlyOffline() || localSeries) {
                    sectionId = await window.electron.invoke<string>('db:series:location:section:add', addData);
                } else {
                    sectionId = await System.authPostToServer<string>(
                        'series/location/section/add',
                        addData,
                        userToken,
                        lang
                    );
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:location:section:add', {...addData, id: sectionId});
                    }
                }
                if (!sectionId) {
                    errorMessage(t('locationComponent.errorUnknownAddSection'));
                    return;
                }
            } else {
                const requestData = {
                    bookId: entityId,
                    locationName: newSectionName,
                };
                if (isCurrentlyOffline() || book?.localBook) {
                    sectionId = await window.electron.invoke<string>('db:location:section:add', requestData);
                } else {
                    sectionId = await System.authPostToServer<string>('location/section/add', requestData, userToken, lang);

                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:section:add', {...requestData, id: sectionId});
                    }
                }
                if (!sectionId) {
                    errorMessage(t('locationComponent.errorUnknownAddSection'));
                    return;
                }
            }
            const newLocation: LocationProps = {
                id: sectionId,
                name: newSectionName,
                elements: [],
            };
            setSections(function (prev: LocationProps[]): LocationProps[] {
                return [...prev, newLocation];
            });
            setNewSectionName('');
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownAddSection'));
            }
        } finally {
            setIsAddingSection(false);
        }
    }, [newSectionName, isSeriesMode, entityId, userToken, lang, errorMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, book, isAddingSection]);

    const addElement = useCallback(async function (sectionId: string): Promise<void> {
        if (isAddingElement) return;
        if (!newElementNames[sectionId]?.trim()) {
            errorMessage(t('locationComponent.errorElementNameEmpty'));
            return;
        }
        setIsAddingElement(true);
        try {
            let elementId: string;
            if (isSeriesMode) {
                // Series mode - dual logic
                const addData = {
                    locationId: sectionId,
                    name: newElementNames[sectionId],
                };
                if (isCurrentlyOffline() || localSeries) {
                    elementId = await window.electron.invoke<string>('db:series:location:element:add', addData);
                } else {
                    elementId = await System.authPostToServer<string>(
                        'series/location/element/add',
                        addData,
                        userToken,
                        lang
                    );
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:location:element:add', {...addData, id: elementId});
                    }
                }
                if (!elementId) {
                    errorMessage(t('locationComponent.errorUnknownAddElement'));
                    return;
                }
            } else {
                const requestData = {
                    bookId: entityId,
                    locationId: sectionId,
                    elementName: newElementNames[sectionId],
                };
                if (isCurrentlyOffline() || book?.localBook) {
                    elementId = await window.electron.invoke<string>('db:location:element:add', requestData);
                } else {
                    elementId = await System.authPostToServer<string>('location/element/add', requestData, userToken, lang);

                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:element:add', {...requestData, id: elementId});
                    }
                }
                if (!elementId) {
                    errorMessage(t('locationComponent.errorUnknownAddElement'));
                    return;
                }
            }
            setSections(function (prev: LocationProps[]): LocationProps[] {
                const updated: LocationProps[] = [...prev];
                const sectionIndex: number = updated.findIndex(function (section: LocationProps): boolean {
                    return section.id === sectionId;
                });
                updated[sectionIndex].elements.push({
                    id: elementId,
                    name: newElementNames[sectionId],
                    description: '',
                    subElements: [],
                });
                return updated;
            });
            setNewElementNames(function (prev: { [key: string]: string }): { [key: string]: string } {
                return {...prev, [sectionId]: ''};
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownAddElement'));
            }
        } finally {
            setIsAddingElement(false);
        }
    }, [newElementNames, isSeriesMode, entityId, userToken, lang, errorMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, book, isAddingElement]);

    const addSubElement = useCallback(async function (sectionId: string, elementIndex: number): Promise<void> {
        if (isAddingSubElement) return;
        if (!newSubElementNames[elementIndex]?.trim()) {
            errorMessage(t('locationComponent.errorSubElementNameEmpty'));
            return;
        }
        setIsAddingSubElement(true);
        const sectionIndex: number = sections.findIndex(function (section: LocationProps): boolean {
            return section.id === sectionId;
        });
        try {
            let subElementId: string;
            if (isSeriesMode) {
                // Series mode - dual logic
                const addData = {
                    elementId: sections[sectionIndex].elements[elementIndex].id,
                    name: newSubElementNames[elementIndex],
                };
                if (isCurrentlyOffline() || localSeries) {
                    subElementId = await window.electron.invoke<string>('db:series:location:subelement:add', addData);
                } else {
                    subElementId = await System.authPostToServer<string>(
                        'series/location/sub-element/add',
                        addData,
                        userToken,
                        lang
                    );
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:location:subelement:add', {...addData, id: subElementId});
                    }
                }
                if (!subElementId) {
                    errorMessage(t('locationComponent.errorUnknownAddSubElement'));
                    return;
                }
            } else {
                const requestData = {
                    elementId: sections[sectionIndex].elements[elementIndex].id,
                    subElementName: newSubElementNames[elementIndex],
                };
                if (isCurrentlyOffline() || book?.localBook) {
                    subElementId = await window.electron.invoke<string>('db:location:subelement:add', requestData);
                } else {
                    subElementId = await System.authPostToServer<string>('location/sub-element/add', requestData, userToken, lang);

                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:subelement:add', {...requestData, id: subElementId});
                    }
                }
                if (!subElementId) {
                    errorMessage(t('locationComponent.errorUnknownAddSubElement'));
                    return;
                }
            }
            setSections(function (prev: LocationProps[]): LocationProps[] {
                const updated: LocationProps[] = [...prev];
                updated[sectionIndex].elements[elementIndex].subElements.push({
                    id: subElementId,
                    name: newSubElementNames[elementIndex],
                    description: '',
                });
                return updated;
            });
            setNewSubElementNames(function (prev: { [key: string]: string }): { [key: string]: string } {
                return {...prev, [elementIndex]: ''};
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownAddSubElement'));
            }
        } finally {
            setIsAddingSubElement(false);
        }
    }, [sections, newSubElementNames, isSeriesMode, userToken, lang, errorMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, entityId, book, isAddingSubElement]);

    const removeSection = useCallback(async function (sectionId: string): Promise<void> {
        try {
            let success: boolean;
            const deletedAt: number = System.timeStampInSeconds();
            if (isSeriesMode) {
                // Series mode - dual logic
                const deleteData = {locationId: sectionId, deletedAt};
                if (isCurrentlyOffline() || localSeries) {
                    success = await window.electron.invoke<boolean>('db:series:location:delete', deleteData);
                } else {
                    success = await System.authDeleteToServer<boolean>('series/location/delete', deleteData, userToken, lang);
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:location:delete', deleteData);
                    }
                }
            } else {
                const requestData = {
                    locationId: sectionId, bookId: entityId, deletedAt,
                };
                if (isCurrentlyOffline() || book?.localBook) {
                    success = await window.electron.invoke<boolean>('db:location:delete', requestData);
                } else {
                    success = await System.authDeleteToServer<boolean>('location/delete', requestData, userToken, lang);

                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:delete', requestData);
                    }
                }
            }
            if (!success) {
                errorMessage(t('locationComponent.errorUnknownDeleteSection'));
                return;
            }
            setSections(function (prev: LocationProps[]): LocationProps[] {
                return prev.filter(function (section: LocationProps): boolean {
                    return section.id !== sectionId;
                });
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownDeleteSection'));
            }
        }
    }, [isSeriesMode, userToken, lang, errorMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, entityId, book]);

    const removeElement = useCallback(async function (sectionId: string, elementIndex: number): Promise<void> {
        try {
            const elementId: string | undefined = sections.find(function (section: LocationProps): boolean {
                return section.id === sectionId;
            })?.elements[elementIndex].id;
            let success: boolean;
            const deletedAt: number = System.timeStampInSeconds();
            if (isSeriesMode) {
                // Series mode - dual logic
                const deleteData = {elementId, deletedAt};
                if (isCurrentlyOffline() || localSeries) {
                    success = await window.electron.invoke<boolean>('db:series:location:element:delete', deleteData);
                } else {
                    success = await System.authDeleteToServer<boolean>('series/location/element/delete', deleteData, userToken, lang);
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:location:element:delete', deleteData);
                    }
                }
            } else {
                const requestData = {
                    elementId, bookId: entityId, deletedAt,
                };
                if (isCurrentlyOffline() || book?.localBook) {
                    success = await window.electron.invoke<boolean>('db:location:element:delete', requestData);
                } else {
                    success = await System.authDeleteToServer<boolean>('location/element/delete', requestData, userToken, lang);

                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:element:delete', requestData);
                    }
                }
            }
            if (!success) {
                errorMessage(t('locationComponent.errorUnknownDeleteElement'));
                return;
            }
            setSections(function (prev: LocationProps[]): LocationProps[] {
                const updated: LocationProps[] = [...prev];
                const sectionIndex: number = updated.findIndex(function (section: LocationProps): boolean {
                    return section.id === sectionId;
                });
                updated[sectionIndex].elements.splice(elementIndex, 1);
                return updated;
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownDeleteElement'));
            }
        }
    }, [sections, isSeriesMode, userToken, lang, errorMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, entityId, book]);

    const removeSubElement = useCallback(async function (sectionId: string, elementIndex: number, subElementIndex: number): Promise<void> {
        try {
            const subElementId: string | undefined = sections.find(function (section: LocationProps): boolean {
                return section.id === sectionId;
            })?.elements[elementIndex].subElements[subElementIndex].id;
            let success: boolean;
            const deletedAt: number = System.timeStampInSeconds();
            if (isSeriesMode) {
                // Series mode - dual logic
                const deleteData = {subElementId, deletedAt};
                if (isCurrentlyOffline() || localSeries) {
                    success = await window.electron.invoke<boolean>('db:series:location:subelement:delete', deleteData);
                } else {
                    success = await System.authDeleteToServer<boolean>('series/location/sub-element/delete', deleteData, userToken, lang);
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:location:subelement:delete', deleteData);
                    }
                }
            } else {
                const requestData = {
                    subElementId, bookId: entityId, deletedAt,
                };
                if (isCurrentlyOffline() || book?.localBook) {
                    success = await window.electron.invoke<boolean>('db:location:subelement:delete', requestData);
                } else {
                    success = await System.authDeleteToServer<boolean>('location/sub-element/delete', requestData, userToken, lang);

                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:subelement:delete', requestData);
                    }
                }
            }
            if (!success) {
                errorMessage(t('locationComponent.errorUnknownDeleteSubElement'));
                return;
            }
            setSections(function (prev: LocationProps[]): LocationProps[] {
                const updated: LocationProps[] = [...prev];
                const sectionIndex: number = updated.findIndex(function (section: LocationProps): boolean {
                    return section.id === sectionId;
                });
                updated[sectionIndex].elements[elementIndex].subElements.splice(subElementIndex, 1);
                return updated;
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownDeleteSubElement'));
            }
        }
    }, [sections, isSeriesMode, userToken, lang, errorMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, entityId, book]);

    const updateElement = useCallback(function (sectionId: string, elementIndex: number, field: keyof Element, value: string): void {
        setSections(function (prev: LocationProps[]): LocationProps[] {
            const updated: LocationProps[] = [...prev];
            const sectionIndex: number = updated.findIndex(function (section: LocationProps): boolean {
                return section.id === sectionId;
            });
            // @ts-ignore
            updated[sectionIndex].elements[elementIndex][field] = value;
            return updated;
        });
    }, []);

    const updateSubElement = useCallback(function (sectionId: string, elementIndex: number, subElementIndex: number, field: keyof SubElement, value: string): void {
        setSections(function (prev: LocationProps[]): LocationProps[] {
            const updated: LocationProps[] = [...prev];
            const sectionIndex: number = updated.findIndex(function (section: LocationProps): boolean {
                return section.id === sectionId;
            });
            updated[sectionIndex].elements[elementIndex].subElements[subElementIndex][field] = value;
            return updated;
        });
    }, []);

    const saveLocations = useCallback(async function (): Promise<boolean> {
        try {
            const requestData = {
                locations: sections,
            };
            let response: boolean;
            if (isCurrentlyOffline() || book?.localBook) {
                response = await window.electron.invoke<boolean>('db:location:update', requestData);
            } else {
                response = await System.authPostToServer<boolean>('location/update', requestData, userToken, lang);

                if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                    addToQueue('db:location:update', requestData);
                }
            }
            if (!response) {
                errorMessage(t('locationComponent.errorUnknownSave'));
                return false;
            }
            successMessage(t('locationComponent.successSave'));
            return true;
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('locationComponent.errorUnknownSave'));
            }
            return false;
        }
    }, [sections, userToken, lang, errorMessage, successMessage, t, isCurrentlyOffline, addToQueue, localSyncedBooks, entityId, book]);

    const exportToSeries = useCallback(async function (section: LocationProps): Promise<void> {
        if (!bookSeriesId) return;

        try {
            const seriesLocationData = {
                seriesId: bookSeriesId,
                name: section.name,
            };

            let seriesLocationId: string;
            if (isCurrentlyOffline() || book?.localBook) {
                // Mode offline ou livre local → IPC
                seriesLocationId = await window.electron.invoke<string>('db:series:location:section:add', seriesLocationData);
            } else {
                // Mode online → Serveur
                seriesLocationId = await System.authPostToServer<string>('series/location/section/add', seriesLocationData, userToken, lang);
                // Si la série a une copie locale → addToQueue avec l'ID du serveur
                if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === bookSeriesId)) {
                    addToQueue('db:series:location:section:add', {...seriesLocationData, id: seriesLocationId});
                }
            }

            if (seriesLocationId) {
                const updateData = {
                    sectionId: section.id,
                    sectionName: section.name,
                    seriesLocationId: seriesLocationId,
                };

                let updateResponse: boolean;
                if (isCurrentlyOffline() || book?.localBook) {
                    // Mode offline ou livre local → IPC
                    updateResponse = await window.electron.invoke<boolean>('db:location:section:update', updateData);
                } else {
                    // Mode online → Serveur
                    updateResponse = await System.authPostToServer<boolean>('location/section/update', updateData, userToken, lang);
                    // Si le livre a une copie locale → addToQueue
                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:section:update', updateData);
                    }
                }

                if (updateResponse) {
                    setSections(function (prev: LocationProps[]): LocationProps[] {
                        return prev.map(function (s: LocationProps): LocationProps {
                            return s.id === section.id ? {...s, seriesLocationId: seriesLocationId} : s;
                        });
                    });
                    const newSeriesLocation: SeriesLocationItem = {
                        id: seriesLocationId,
                        name: section.name,
                        elements: [],
                    };
                    setSeriesLocations(function (prev: SeriesLocationItem[]): SeriesLocationItem[] {
                        return [...prev, newSeriesLocation];
                    });
                    successMessage(t("locationComponent.exportSuccess"));
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [bookSeriesId, userToken, lang, successMessage, errorMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks, localSyncedSeries, entityId]);

    const importFromSeries = useCallback(async function (seriesLocationId: string): Promise<void> {
        const seriesLocation: SeriesLocationItem | undefined = seriesLocations.find(function (location: SeriesLocationItem): boolean {
            return location.id === seriesLocationId;
        });
        if (!seriesLocation) return;

        try {
            const sectionData = {
                bookId: entityId,
                locationName: seriesLocation.name,
                seriesLocationId: seriesLocationId,
            };

            let sectionId: string;
            if (isCurrentlyOffline() || book?.localBook) {
                // Mode offline ou livre local → IPC
                sectionId = await window.electron.invoke<string>('db:location:section:add', sectionData);
            } else {
                // Mode online → Serveur
                sectionId = await System.authPostToServer<string>('location/section/add', sectionData, userToken, lang);
                // Si le livre a une copie locale → addToQueue avec l'ID du serveur
                if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                    addToQueue('db:location:section:add', {...sectionData, id: sectionId});
                }
            }

            if (!sectionId) {
                errorMessage(t('locationComponent.importError'));
                return;
            }

            const importedElements: Element[] = [];

            for (const seriesElement of seriesLocation.elements) {
                const elementData = {
                    bookId: entityId,
                    locationId: sectionId,
                    elementName: seriesElement.name,
                };

                let elementId: string;
                if (isCurrentlyOffline() || book?.localBook) {
                    // Mode offline ou livre local → IPC
                    elementId = await window.electron.invoke<string>('db:location:element:add', elementData);
                } else {
                    // Mode online → Serveur
                    elementId = await System.authPostToServer<string>('location/element/add', elementData, userToken, lang);
                    // Si le livre a une copie locale → addToQueue avec l'ID du serveur
                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:location:element:add', {...elementData, id: elementId});
                    }
                }

                if (!elementId) continue;

                const importedSubElements: SubElement[] = [];

                for (const seriesSubElement of seriesElement.subElements) {
                    const subElementData = {
                        elementId: elementId,
                        subElementName: seriesSubElement.name,
                    };

                    let subElementId: string;
                    if (isCurrentlyOffline() || book?.localBook) {
                        // Mode offline ou livre local → IPC
                        subElementId = await window.electron.invoke<string>('db:location:subelement:add', subElementData);
                    } else {
                        // Mode online → Serveur
                        subElementId = await System.authPostToServer<string>('location/sub-element/add', subElementData, userToken, lang);
                        // Si le livre a une copie locale → addToQueue avec l'ID du serveur
                        if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                            addToQueue('db:location:subelement:add', {...subElementData, id: subElementId});
                        }
                    }

                    if (subElementId) {
                        importedSubElements.push({
                            id: subElementId,
                            name: seriesSubElement.name,
                            description: seriesSubElement.description,
                        });
                    }
                }

                importedElements.push({
                    id: elementId,
                    name: seriesElement.name,
                    description: seriesElement.description,
                    subElements: importedSubElements,
                });
            }

            const newLocation: LocationProps = {
                id: sectionId,
                name: seriesLocation.name,
                elements: importedElements,
                seriesLocationId: seriesLocationId,
            };
            setSections(function (prev: LocationProps[]): LocationProps[] {
                return [...prev, newLocation];
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [seriesLocations, entityId, userToken, lang, errorMessage, successMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks]);

    // Navigation functions
    const enterDetailMode = useCallback(function (sectionIndex: number): void {
        setSelectedSectionIndex(sectionIndex);
        setViewMode('detail');
        setSectionsBackup(null);
    }, []);

    const enterEditMode = useCallback(function (): void {
        setSectionsBackup(sections.map(function (section: LocationProps): LocationProps {
            return {
                ...section,
                elements: section.elements.map(function (element: Element): Element {
                    return {
                        ...element,
                        subElements: [...element.subElements]
                    };
                })
            };
        }));
        setViewMode('edit');
    }, [sections]);

    const exitEditMode = useCallback(async function (save: boolean): Promise<void> {
        if (save) {
            const success: boolean = await saveLocations();
            if (!success) {
                // Stay in edit mode on error
                return;
            }
            setViewMode('detail');
        } else {
            if (sectionsBackup) {
                setSections(sectionsBackup);
                setViewMode('detail');
            } else {
                setViewMode('list');
            }
        }
        setSectionsBackup(null);
    }, [saveLocations, sectionsBackup]);

    const backToList = useCallback(function (): void {
        setSelectedSectionIndex(-1);
        setSectionsBackup(null);
        setViewMode('list');
    }, []);

    return {
        // State
        sections,
        seriesLocations,
        toolEnabled,
        isLoading,
        isSeriesMode,
        bookSeriesId,
        newSectionName,
        newElementNames,
        newSubElementNames,

        // Navigation state
        viewMode,
        selectedSectionIndex,
        sectionsBackup,

        // Actions
        addSection,
        addElement,
        addSubElement,
        removeSection,
        removeElement,
        removeSubElement,
        updateElement,
        updateSubElement,
        saveLocations,
        toggleTool,
        importFromSeries,
        exportToSeries,
        refreshLocations,
        refreshSeriesLocations,
        setNewSectionName,
        setNewElementNames,
        setNewSubElementNames,

        // Navigation actions
        enterDetailMode,
        enterEditMode,
        exitEditMode,
        backToList,
    };
}
