'use client'
import {useCallback, useContext, useEffect, useState} from 'react';
import {Attribute, CharacterListResponse, CharacterProps} from '@/lib/models/Character';
import {SeriesCharacterProps} 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 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';
import System from '@/lib/models/System';
import {useTranslations} from 'next-intl';
import {ViewMode} from '@/shared/interface';

const initialCharacterState: CharacterProps = {
    id: null,
    name: '',
    lastName: '',
    nickname: '',
    age: null,
    gender: '',
    species: '',
    nationality: '',
    status: 'alive',
    category: 'none',
    title: '',
    role: '',
    image: 'https://via.placeholder.com/150',
    biography: '',
    history: '',
    speechPattern: '',
    catchphrase: '',
    residence: '',
    notes: '',
    color: '',
    physical: [],
    psychological: [],
    relations: [],
    skills: [],
    weaknesses: [],
    strengths: [],
    goals: [],
    motivations: [],
    arc: [],
    secrets: [],
    fears: [],
    flaws: [],
    beliefs: [],
    conflicts: [],
    quotes: [],
    distinguishingMarks: [],
    items: [],
    affiliations: [],
};

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

export interface UseCharactersReturn {
    // State
    characters: CharacterProps[];
    seriesCharacters: SeriesCharacterProps[];
    selectedCharacter: CharacterProps | null;
    toolEnabled: boolean;
    isLoading: boolean;
    isSeriesMode: boolean;
    bookSeriesId: string | null;

    // Navigation state
    viewMode: ViewMode;
    characterBackup: CharacterProps | null;

    // Actions
    selectCharacter: (character: CharacterProps) => void;
    addNewCharacter: () => void;
    clearSelection: () => void;
    saveCharacter: () => Promise<boolean>;
    deleteCharacter: (characterId: string) => Promise<void>;
    updateCharacterField: (key: keyof CharacterProps, value: string | number | null) => void;
    addAttribute: (section: keyof CharacterProps, value: Attribute) => Promise<void>;
    removeAttribute: (section: keyof CharacterProps, index: number, attrId: string) => Promise<void>;
    toggleTool: (enabled: boolean) => Promise<void>;
    importFromSeries: (seriesCharacterId: string) => Promise<void>;
    exportToSeries: () => Promise<void>;
    refreshCharacters: () => Promise<void>;
    refreshSeriesCharacters: () => Promise<void>;
    setSelectedCharacter: React.Dispatch<React.SetStateAction<CharacterProps | null>>;

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

export function useCharacters(config: UseCharactersConfig): UseCharactersReturn {
    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 [characters, setCharacters] = useState<CharacterProps[]>([]);
    const [seriesCharacters, setSeriesCharacters] = useState<SeriesCharacterProps[]>([]);
    const [selectedCharacter, setSelectedCharacter] = useState<CharacterProps | null>(null);
    const [toolEnabled, setToolEnabled] = useState<boolean>(entityType === 'series' || (book?.tools?.characters ?? false));
    const [isLoading, setIsLoading] = useState<boolean>(true);

    // Navigation state
    const [viewMode, setViewMode] = useState<ViewMode>('list');
    const [characterBackup, setCharacterBackup] = useState<CharacterProps | null>(null);

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

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

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

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

    const refreshCharacters = useCallback(async function (): Promise<void> {
        setIsLoading(true);
        try {
            if (isSeriesMode) {
                // Series mode - dual logic
                let response: SeriesCharacterProps[];
                if (isCurrentlyOffline() || localSeries) {
                    response = await window.electron.invoke<SeriesCharacterProps[]>(
                        'db:series:character:list',
                        {seriesId: entityId}
                    );
                } else {
                    response = await System.authGetQueryToServer<SeriesCharacterProps[]>(
                        'series/character/list',
                        userToken,
                        lang,
                        {seriesid: entityId}
                    );
                }
                if (response) {
                    const mappedCharacters: CharacterProps[] = response.map(function (char: SeriesCharacterProps): CharacterProps {
                        return {
                            id: char.id,
                            name: char.name,
                            lastName: char.lastName || '',
                            nickname: '',
                            age: char.age ?? null,
                            gender: '',
                            species: '',
                            nationality: '',
                            status: 'alive' as const,
                            category: char.category as CharacterProps['category'],
                            title: '',
                            role: char.role || '',
                            image: char.image || 'https://via.placeholder.com/150',
                            color: char.color || '',
                            physical: [],
                            psychological: [],
                            relations: [],
                            skills: [],
                            weaknesses: [],
                            strengths: [],
                            goals: [],
                            motivations: [],
                            arc: [],
                            secrets: [],
                            fears: [],
                            flaws: [],
                            beliefs: [],
                            conflicts: [],
                            quotes: [],
                            distinguishingMarks: [],
                            items: [],
                            affiliations: [],
                        };
                    });
                    setCharacters(mappedCharacters);
                }
            } else {
                // Pattern B: GET dans contexte livre
                let response: CharacterListResponse;
                if (isCurrentlyOffline()) {
                    // Offline → IPC
                    response = await window.electron.invoke<CharacterListResponse>('db:character:list', {bookid: entityId});
                } else if (book?.localBook) {
                    // Online mais livre local → IPC
                    response = await window.electron.invoke<CharacterListResponse>('db:character:list', {bookid: entityId});
                } else {
                    // Online + livre serveur → Server
                    response = await System.authGetQueryToServer<CharacterListResponse>(
                        'character/list',
                        userToken,
                        lang,
                        {bookid: entityId}
                    );
                }
                if (response) {
                    setCharacters(response.characters);
                    setToolEnabled(response.enabled);
                    if (setBook && book) {
                        setBook({
                            ...book,
                            tools: {
                                characters: response.enabled,
                                worlds: book.tools?.worlds ?? false,
                                locations: book.tools?.locations ?? false,
                                spells: book.tools?.spells ?? false
                            }
                        });
                    }
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("common.unknownError"));
            }
        } finally {
            setIsLoading(false);
        }
    }, [entityId, isSeriesMode, userToken, lang, book, setBook, errorMessage, t, isCurrentlyOffline]);

    const selectCharacter = useCallback(function (character: CharacterProps): void {
        setSelectedCharacter({...character});
    }, []);

    const addNewCharacter = useCallback(function (): void {
        setSelectedCharacter({...initialCharacterState});
        setViewMode('edit');
        setCharacterBackup(null);
    }, []);

    const clearSelection = useCallback(function (): void {
        setSelectedCharacter(null);
        setViewMode('list');
        setCharacterBackup(null);
    }, []);

    const updateCharacterField = useCallback(function (key: keyof CharacterProps, value: string | number | null): void {
        setSelectedCharacter(function (prev: CharacterProps | null): CharacterProps | null {
            if (!prev) return null;
            return {...prev, [key]: value};
        });
    }, []);

    const toggleTool = useCallback(async function (enabled: boolean): Promise<void> {
        if (isSeriesMode) return;
        try {
            const requestData = {
                bookId: book?.bookId,
                toolName: 'characters',
                enabled: enabled
            };

            let response: boolean;
            if (isCurrentlyOffline() || book?.localBook) {
                // Offline OU livre local → IPC
                response = await window.electron.invoke<boolean>('db:book:tool:update', requestData);
            } else {
                // Online + livre serveur → Server
                response = await System.authPatchToServer<boolean>('book/tool-setting', requestData, userToken, lang);

                // Si le livre a une copie locale → addToQueue pour sync
                if (book?.bookId && 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: enabled,
                        worlds: book.tools?.worlds ?? false,
                        locations: book.tools?.locations ?? false,
                        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 saveCharacter = useCallback(async function (): Promise<boolean> {
        if (!selectedCharacter) return false;

        if (selectedCharacter.id === null) {
            return await addCharacterInternal(selectedCharacter);
        } else {
            return await updateCharacterInternal(selectedCharacter);
        }
    }, [selectedCharacter]);

    async function addCharacterInternal(character: CharacterProps): Promise<boolean> {
        if (!character.name) {
            errorMessage(t("characterComponent.errorNameRequired"));
            return false;
        }
        if (character.category === 'none') {
            errorMessage(t("characterComponent.errorCategoryRequired"));
            return false;
        }
        try {
            let characterId: string;
            if (isSeriesMode) {
                // Series mode - dual logic
                const seriesCharacterData = {
                    seriesId: entityId,
                    character: {
                        name: character.name,
                        lastName: character.lastName || null,
                        nickname: character.nickname || null,
                        age: character.age || null,
                        gender: character.gender || null,
                        species: character.species || null,
                        nationality: character.nationality || null,
                        status: character.status || null,
                        category: character.category,
                        title: character.title || null,
                        image: character.image || null,
                        role: character.role || null,
                        biography: character.biography || null,
                        history: character.history || null,
                        speechPattern: character.speechPattern || null,
                        catchphrase: character.catchphrase || null,
                        residence: character.residence || null,
                        notes: character.notes || null,
                        color: character.color || null,
                    }
                };
                if (isCurrentlyOffline() || localSeries) {
                    characterId = await window.electron.invoke<string>('db:series:character:add', seriesCharacterData);
                } else {
                    characterId = await System.authPostToServer<string>(
                        'series/character/add',
                        seriesCharacterData,
                        userToken,
                        lang
                    );
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:character:add', {...seriesCharacterData, id: characterId});
                    }
                }
            } else {
                // Pattern A: mutations
                const requestData = {
                    bookId: entityId,
                    character: character,
                };

                if (isCurrentlyOffline() || book?.localBook) {
                    // Offline OU livre local → IPC
                    characterId = await window.electron.invoke<string>('db:character:create', requestData);
                } else {
                    // Online + livre serveur → Server
                    characterId = await System.authPostToServer<string>('character/add', requestData, userToken, lang);

                    // Si le livre a une copie locale → addToQueue pour sync
                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:character:create', {...requestData, id: characterId});
                    }
                }
            }

            if (!characterId) {
                errorMessage(t("characterComponent.errorAddCharacter"));
                return false;
            }

            const newCharacter: CharacterProps = {...character, id: characterId};
            setCharacters(function (prev: CharacterProps[]): CharacterProps[] {
                return [...prev, newCharacter];
            });
            setSelectedCharacter(null);
            return true;
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("common.unknownError"));
            }
            return false;
        }
    }

    async function updateCharacterInternal(character: CharacterProps): Promise<boolean> {
        try {
            let response: boolean;
            if (isSeriesMode) {
                // Series mode - dual logic
                const updateData = {
                    characterId: character.id,
                    character: {
                        id: character.id,
                        name: character.name,
                        lastName: character.lastName || null,
                        nickname: character.nickname || null,
                        age: character.age || null,
                        gender: character.gender || null,
                        species: character.species || null,
                        nationality: character.nationality || null,
                        status: character.status || null,
                        category: character.category,
                        title: character.title || null,
                        image: character.image || null,
                        role: character.role || null,
                        biography: character.biography || null,
                        history: character.history || null,
                        speechPattern: character.speechPattern || null,
                        catchphrase: character.catchphrase || null,
                        residence: character.residence || null,
                        notes: character.notes || null,
                        color: character.color || null,
                    }
                };
                if (isCurrentlyOffline() || localSeries) {
                    response = await window.electron.invoke<boolean>('db:series:character:update', updateData);
                } else {
                    response = await System.authPatchToServer<boolean>('series/character/update', updateData, userToken, lang);
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:character:update', updateData);
                    }
                }
            } else {
                // Pattern A: mutations
                const requestData = {
                    character: character,
                };

                if (isCurrentlyOffline() || book?.localBook) {
                    // Offline OU livre local → IPC
                    response = await window.electron.invoke<boolean>('db:character:update', requestData);
                } else {
                    // Online + livre serveur → Server
                    response = await System.authPostToServer<boolean>('character/update', requestData, userToken, lang);

                    // Si le livre a une copie locale → addToQueue pour sync
                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:character:update', requestData);
                    }
                }
            }

            if (!response) {
                errorMessage(t("characterComponent.errorUpdateCharacter"));
                return false;
            }

            setCharacters(function (prev: CharacterProps[]): CharacterProps[] {
                return prev.map(function (c: CharacterProps): CharacterProps {
                    return c.id === character.id ? character : c;
                });
            });
            setSelectedCharacter(null);
            successMessage(t("characterComponent.successUpdate"));
            return true;
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("common.unknownError"));
            }
            return false;
        }
    }

    const deleteCharacter = useCallback(async function (characterId: string): Promise<void> {
        try {
            let response: boolean;
            const deletedAt: number = System.timeStampInSeconds();

            if (isSeriesMode) {
                // Series mode - dual logic
                const requestData = {characterId, deletedAt};
                if (isCurrentlyOffline() || localSeries) {
                    response = await window.electron.invoke<boolean>('db:series:character:delete', requestData);
                } else {
                    response = await System.authDeleteToServer<boolean>('series/character/delete', requestData, userToken, lang);
                    if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                        addToQueue('db:series:character:delete', requestData);
                    }
                }
            } else {
                // Pattern A: mutations
                const requestData = {characterId, bookId: entityId, deletedAt};
                if (isCurrentlyOffline() || book?.localBook) {
                    // Offline OU livre local → IPC
                    response = await window.electron.invoke<boolean>('db:character:delete', requestData);
                } else {
                    // Online + livre serveur → Server
                    response = await System.authDeleteToServer<boolean>('character/delete', requestData, userToken, lang);

                    // Si le livre a une copie locale → addToQueue pour sync
                    if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                        addToQueue('db:character:delete', requestData);
                    }
                }
            }

            if (!response) {
                errorMessage(t("characterComponent.errorDeleteCharacter"));
                return;
            }

            setCharacters(function (prev: CharacterProps[]): CharacterProps[] {
                return prev.filter(function (c: CharacterProps): boolean {
                    return c.id !== characterId;
                });
            });
            setSelectedCharacter(null);
            successMessage(t("characterComponent.successDelete"));
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("common.unknownError"));
            }
        }
    }, [isSeriesMode, userToken, lang, errorMessage, successMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks, entityId]);

    const addAttribute = useCallback(async function (section: keyof CharacterProps, value: Attribute): Promise<void> {
        if (!selectedCharacter) return;

        if (selectedCharacter.id === null) {
            const updatedSection: Attribute[] = [
                ...(selectedCharacter[section] as Attribute[]),
                value,
            ];
            setSelectedCharacter({...selectedCharacter, [section]: updatedSection});
        } else {
            try {
                const requestData = {
                    characterId: selectedCharacter.id,
                    type: section,
                    name: value.name,
                };

                let attributeId: string;
                if (isSeriesMode) {
                    // Series mode - dual logic
                    if (isCurrentlyOffline() || localSeries) {
                        attributeId = await window.electron.invoke<string>('db:series:character:attribute:add', requestData);
                    } else {
                        attributeId = await System.authPostToServer<string>('series/character/attribute/add', requestData, userToken, lang);
                        if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                            addToQueue('db:series:character:attribute:add', {...requestData, id: attributeId});
                        }
                    }
                } else {
                    // Pattern A: mutations
                    if (isCurrentlyOffline() || book?.localBook) {
                        // Offline OU livre local → IPC
                        attributeId = await window.electron.invoke<string>('db:character:attribute:add', requestData);
                    } else {
                        // Online + livre serveur → Server
                        attributeId = await System.authPostToServer<string>('character/attribute/add', requestData, userToken, lang);

                        // Si le livre a une copie locale → addToQueue pour sync
                        if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                            addToQueue('db:character:attribute:add', {...requestData, id: attributeId});
                        }
                    }
                }

                if (!attributeId) {
                    errorMessage(t("characterComponent.errorAddAttribute"));
                    return;
                }

                const newValue: Attribute = {
                    name: value.name,
                    id: attributeId,
                };
                const updatedSection: Attribute[] = [...(selectedCharacter[section] as Attribute[]), newValue];
                setSelectedCharacter({...selectedCharacter, [section]: updatedSection});
            } catch (e: unknown) {
                if (e instanceof Error) {
                    errorMessage(e.message);
                } else {
                    errorMessage(t("common.unknownError"));
                }
            }
        }
    }, [selectedCharacter, isSeriesMode, userToken, lang, errorMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks, entityId]);

    const removeAttribute = useCallback(async function (section: keyof CharacterProps, index: number, attrId: string): Promise<void> {
        if (!selectedCharacter) return;

        if (selectedCharacter.id === null) {
            const updatedSection: Attribute[] = (
                selectedCharacter[section] as Attribute[]
            ).filter(function (_: Attribute, i: number): boolean {
                return i !== index;
            });
            setSelectedCharacter({...selectedCharacter, [section]: updatedSection});
        } else {
            try {
                const deletedAt: number = System.timeStampInSeconds();

                let response: boolean;
                if (isSeriesMode) {
                    // Series mode - dual logic
                    const requestData = {attributeId: attrId, deletedAt};
                    if (isCurrentlyOffline() || localSeries) {
                        response = await window.electron.invoke<boolean>('db:series:character:attribute:delete', requestData);
                    } else {
                        response = await System.authDeleteToServer<boolean>('series/character/attribute/delete', requestData, userToken, lang);
                        if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === entityId)) {
                            addToQueue('db:series:character:attribute:delete', requestData);
                        }
                    }
                } else {
                    // Pattern A: mutations
                    const requestData = {attributeId: attrId, bookId: entityId, deletedAt};
                    if (isCurrentlyOffline() || book?.localBook) {
                        // Offline OU livre local → IPC
                        response = await window.electron.invoke<boolean>('db:character:attribute:delete', requestData);
                    } else {
                        // Online + livre serveur → Server
                        response = await System.authDeleteToServer<boolean>('character/attribute/delete', requestData, userToken, lang);

                        // Si le livre a une copie locale → addToQueue pour sync
                        if (localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === entityId)) {
                            addToQueue('db:character:attribute:delete', requestData);
                        }
                    }
                }

                if (!response) {
                    errorMessage(t("characterComponent.errorRemoveAttribute"));
                    return;
                }

                const updatedSection: Attribute[] = (
                    selectedCharacter[section] as Attribute[]
                ).filter(function (_: Attribute, i: number): boolean {
                    return i !== index;
                });
                setSelectedCharacter({...selectedCharacter, [section]: updatedSection});
            } catch (e: unknown) {
                if (e instanceof Error) {
                    errorMessage(e.message);
                } else {
                    errorMessage(t("common.unknownError"));
                }
            }
        }
    }, [selectedCharacter, isSeriesMode, userToken, lang, errorMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks, entityId]);

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

        try {
            const seriesCharacterData = {
                seriesId: bookSeriesId,
                character: {
                    name: selectedCharacter.name,
                    lastName: selectedCharacter.lastName || null,
                    nickname: selectedCharacter.nickname || null,
                    age: selectedCharacter.age || null,
                    gender: selectedCharacter.gender || null,
                    species: selectedCharacter.species || null,
                    nationality: selectedCharacter.nationality || null,
                    status: selectedCharacter.status || null,
                    category: selectedCharacter.category,
                    title: selectedCharacter.title || null,
                    image: selectedCharacter.image || null,
                    role: selectedCharacter.role || null,
                    biography: selectedCharacter.biography || null,
                    history: selectedCharacter.history || null,
                    speechPattern: selectedCharacter.speechPattern || null,
                    catchphrase: selectedCharacter.catchphrase || null,
                    residence: selectedCharacter.residence || null,
                    notes: selectedCharacter.notes || null,
                    color: selectedCharacter.color || null,
                }
            };

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

            if (seriesCharacterId) {
                const updateData = {
                    character: {
                        ...selectedCharacter,
                        seriesCharacterId: seriesCharacterId
                    },
                };

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

                if (updateResponse) {
                    setSelectedCharacter({...selectedCharacter, seriesCharacterId: seriesCharacterId});
                    setCharacters(function (prev: CharacterProps[]): CharacterProps[] {
                        return prev.map(function (c: CharacterProps): CharacterProps {
                            return c.id === selectedCharacter.id ? {...c, seriesCharacterId: seriesCharacterId} : c;
                        });
                    });
                    const newSeriesCharacter: SeriesCharacterProps = {
                        id: seriesCharacterId,
                        name: selectedCharacter.name,
                        lastName: selectedCharacter.lastName || null,
                        nickname: selectedCharacter.nickname || null,
                        age: selectedCharacter.age || null,
                        gender: selectedCharacter.gender || null,
                        species: selectedCharacter.species || null,
                        nationality: selectedCharacter.nationality || null,
                        status: selectedCharacter.status || null,
                        category: selectedCharacter.category,
                        title: selectedCharacter.title || null,
                        image: selectedCharacter.image || null,
                        role: selectedCharacter.role || null,
                        biography: selectedCharacter.biography || null,
                        history: selectedCharacter.history || null,
                        speechPattern: selectedCharacter.speechPattern || null,
                        catchphrase: selectedCharacter.catchphrase || null,
                        residence: selectedCharacter.residence || null,
                        notes: selectedCharacter.notes || null,
                        color: selectedCharacter.color || null,
                    };
                    setSeriesCharacters(function (prev: SeriesCharacterProps[]): SeriesCharacterProps[] {
                        return [...prev, newSeriesCharacter];
                    });
                    successMessage(t("characterComponent.exportSuccess"));
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [selectedCharacter, bookSeriesId, userToken, lang, successMessage, errorMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks, localSyncedSeries, entityId]);

    const importFromSeries = useCallback(async function (seriesCharacterId: string): Promise<void> {
        const seriesChar = seriesCharacters.find(function (c: SeriesCharacterProps): boolean {
            return c.id === seriesCharacterId;
        });
        if (!seriesChar) return;

        try {
            const characterToImport: CharacterProps = {
                id: null,
                name: seriesChar.name,
                lastName: seriesChar.lastName || '',
                nickname: seriesChar.nickname || '',
                age: seriesChar.age ?? null,
                gender: seriesChar.gender || '',
                species: seriesChar.species || '',
                nationality: seriesChar.nationality || '',
                status: (seriesChar.status as 'alive' | 'dead' | 'unknown') || 'alive',
                category: (seriesChar.category as CharacterProps['category']) || 'none',
                title: seriesChar.title || '',
                role: seriesChar.role || '',
                image: seriesChar.image || 'https://via.placeholder.com/150',
                biography: seriesChar.biography || '',
                history: seriesChar.history || '',
                speechPattern: seriesChar.speechPattern || '',
                catchphrase: seriesChar.catchphrase || '',
                residence: seriesChar.residence || '',
                notes: seriesChar.notes || '',
                color: seriesChar.color || '',
                physical: [],
                psychological: [],
                relations: [],
                skills: [],
                weaknesses: [],
                strengths: [],
                goals: [],
                motivations: [],
                arc: [],
                secrets: [],
                fears: [],
                flaws: [],
                beliefs: [],
                conflicts: [],
                quotes: [],
                distinguishingMarks: [],
                items: [],
                affiliations: [],
                seriesCharacterId: seriesCharacterId,
            };

            const requestData = {
                bookId: entityId,
                character: characterToImport,
            };

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

            if (!characterId) {
                errorMessage(t("characterComponent.importError"));
                return;
            }

            characterToImport.id = characterId;
            setCharacters(function (prev: CharacterProps[]): CharacterProps[] {
                return [...prev, characterToImport];
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [seriesCharacters, entityId, userToken, lang, errorMessage, successMessage, t, isCurrentlyOffline, book, addToQueue, localSyncedBooks]);

    // Navigation functions
    const enterDetailMode = useCallback(function (character: CharacterProps): void {
        setSelectedCharacter({...character});
        setViewMode('detail');
        setCharacterBackup(null);
    }, []);

    const enterEditMode = useCallback(function (): void {
        if (selectedCharacter) {
            setCharacterBackup({...selectedCharacter});
        }
        setViewMode('edit');
    }, [selectedCharacter]);

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

    const backToList = useCallback(function (): void {
        setSelectedCharacter(null);
        setCharacterBackup(null);
        setViewMode('list');
    }, []);

    return {
        // State
        characters,
        seriesCharacters,
        selectedCharacter,
        toolEnabled,
        isLoading,
        isSeriesMode,
        bookSeriesId,

        // Navigation state
        viewMode,
        characterBackup,

        // Actions
        selectCharacter,
        addNewCharacter,
        clearSelection,
        saveCharacter,
        deleteCharacter,
        updateCharacterField,
        addAttribute,
        removeAttribute,
        toggleTool,
        importFromSeries,
        exportToSeries,
        refreshCharacters,
        refreshSeriesCharacters,
        setSelectedCharacter,

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