'use client'
import {useCallback, useContext, useEffect, useState} from 'react';
import {WorldElement, WorldElementSection, WorldListResponse, WorldProps, WorldTextField} from '@/lib/types/world';
import {SeriesWorldProps} from '@/lib/types/series';
import {SessionContext, SessionContextProps} from '@/context/SessionContext';
import {BookContext, BookContextProps} from '@/context/BookContext';
import {AlertContext, AlertContextProps} from '@/context/AlertContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import {apiGet, apiPatch, apiPost} from '@/lib/api/client';
import {useTranslations} from '@/lib/i18n';
import {SelectBoxProps} from '@/components/form/SelectBox';
import {ViewMode} from '@/lib/types/settings';
import {isDesktop} from '@/lib/configs';
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';

const initialWorldState: WorldProps = {
    id: '',
    name: '',
    history: '',
    politics: '',
    economy: '',
    religion: '',
    languages: '',
    laws: [],
    biomes: [],
    issues: [],
    customs: [],
    kingdoms: [],
    climate: [],
    resources: [],
    wildlife: [],
    arts: [],
    ethnicGroups: [],
    socialClasses: [],
    importantCharacters: [],
};

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

export interface UseWorldsReturn {
    // State
    worlds: WorldProps[];
    seriesWorlds: SeriesWorldProps[];
    selectedWorldIndex: number;
    worldsSelector: SelectBoxProps[];
    toolEnabled: boolean;
    isLoading: boolean;
    isSeriesMode: boolean;
    bookSeriesId: string | null;
    showAddNewWorld: boolean;
    newWorldName: string;
    
    // Navigation state
    viewMode: ViewMode;
    worldBackup: WorldProps | null;
    
    // Actions
    selectWorld: (worldId: string) => void;
    addNewWorld: () => Promise<void>;
    saveWorld: () => Promise<void>;
    updateWorldField: (field: WorldTextField, value: string) => void;
    updateWorldArrayField: (field: WorldElementSection, value: WorldElement[]) => void;
    toggleTool: (enabled: boolean) => Promise<void>;
    importFromSeries: (seriesWorldId: string) => Promise<void>;
    exportToSeries: () => Promise<void>;
    refreshWorlds: () => Promise<void>;
    refreshSeriesWorlds: () => Promise<void>;
    setShowAddNewWorld: (show: boolean) => void;
    setNewWorldName: (name: string) => void;
    setWorlds: React.Dispatch<React.SetStateAction<WorldProps[]>>;
    getSeriesWorldForCurrentWorld: () => SeriesWorldProps | null;
    
    // Navigation actions
    enterDetailMode: (worldId: string) => void;
    enterEditMode: () => void;
    exitEditMode: (save: boolean) => Promise<void>;
    backToList: () => void;
}

export function useWorlds(config: UseWorldsConfig): UseWorldsReturn {
    const {entityType, entityId} = config;
    const t = useTranslations();
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {book, setBook}: BookContextProps = useContext<BookContextProps>(BookContext);
    const {errorMessage, successMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);

    const [worlds, setWorlds] = useState<WorldProps[]>([]);
    const [seriesWorlds, setSeriesWorlds] = useState<SeriesWorldProps[]>([]);
    const [selectedWorldIndex, setSelectedWorldIndex] = useState<number>(0);
    const [worldsSelector, setWorldsSelector] = useState<SelectBoxProps[]>([]);
    const [toolEnabled, setToolEnabled] = useState<boolean>(entityType === 'series' || (book?.tools?.worlds ?? false));
    const [isLoading, setIsLoading] = useState<boolean>(true);
    const [showAddNewWorld, setShowAddNewWorld] = useState<boolean>(false);
    const [newWorldName, setNewWorldName] = useState<string>('');
    
    // Navigation state
    const [viewMode, setViewMode] = useState<ViewMode>('list');
    const [worldBackup, setWorldBackup] = useState<WorldProps | null>(null);
    
    const isSeriesMode: boolean = entityType === 'series';
    const bookSeriesId: string | null = book?.seriesId || null;
    const userToken: string = session?.accessToken || '';
    
    // Load worlds on mount
    useEffect(function (): void {
        if (entityId) {
            refreshWorlds();
        }
    }, [entityId]);
    
    // Load series worlds for book mode
    useEffect(function (): void {
        if (bookSeriesId && !isSeriesMode) {
            refreshSeriesWorlds();
        }
    }, [bookSeriesId, isSeriesMode]);
    
    const refreshSeriesWorlds = useCallback(async function (): Promise<void> {
        if (!bookSeriesId) return;
        try {
            const response: SeriesWorldProps[] = await apiGet<SeriesWorldProps[]>(
                'series/world/list',
                userToken,
                lang,
                {seriesid: bookSeriesId}
            );
            if (response) {
                setSeriesWorlds(response);
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [bookSeriesId, userToken, lang]);
    
    const refreshWorlds = useCallback(async function (): Promise<void> {
        setIsLoading(true);
        try {
            if (isSeriesMode) {
                const response: SeriesWorldProps[] = await apiGet<SeriesWorldProps[]>(
                    'series/world/list',
                    userToken,
                    lang,
                    {seriesid: entityId}
                );
                if (response) {
                    const mappedWorlds: WorldProps[] = response.map(function (world: SeriesWorldProps): WorldProps {
                        return {
                            id: world.id,
                            name: world.name,
                            history: world.history || '',
                            politics: world.politics || '',
                            economy: world.economy || '',
                            religion: world.religion || '',
                            languages: world.languages || '',
                            laws: world.laws || [],
                            biomes: world.biomes || [],
                            issues: world.issues || [],
                            customs: world.customs || [],
                            kingdoms: world.kingdoms || [],
                            climate: world.climate || [],
                            resources: world.resources || [],
                            wildlife: world.wildlife || [],
                            arts: world.arts || [],
                            ethnicGroups: world.ethnicGroups || [],
                            socialClasses: world.socialClasses || [],
                            importantCharacters: world.importantCharacters || [],
                        };
                    });
                    setWorlds(mappedWorlds);
                    const formattedWorlds: SelectBoxProps[] = response.map(function (world: SeriesWorldProps): SelectBoxProps {
                        return {
                            label: world.name,
                            value: world.id,
                        };
                    });
                    setWorldsSelector(formattedWorlds);
                }
            } else {
                let response: WorldListResponse;
                if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                    response = await tauri.getWorlds(entityId, book?.tools?.worlds ?? false) as WorldListResponse;
                } else {
                    response = await apiGet<WorldListResponse>('book/worlds', userToken, lang, {
                        bookid: entityId
                    });
                }
                if (response) {
                    setWorlds(response.worlds);
                    setToolEnabled(response.enabled);
                    if (setBook && book) {
                        setBook({
                            ...book,
                            tools: {
                                characters: book.tools?.characters ?? false,
                                worlds: response.enabled,
                                locations: book.tools?.locations ?? false,
                                spells: book.tools?.spells ?? false
                            }
                        });
                    }
                    const formattedWorlds: SelectBoxProps[] = response.worlds.map(function (world: WorldProps): SelectBoxProps {
                        return {
                            label: world.name,
                            value: world.id.toString(),
                        };
                    });
                    setWorldsSelector(formattedWorlds);
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("worldSetting.unknownError"));
            }
        } finally {
            setIsLoading(false);
        }
    }, [entityId, isSeriesMode, userToken, lang, book, setBook, errorMessage, t]);
    
    const selectWorld = useCallback(function (worldId: string): void {
        const index: number = worlds.findIndex(function (world: WorldProps): boolean {
            return world.id === worldId;
        });
        if (index !== -1) {
            setSelectedWorldIndex(index);
        }
    }, [worlds]);
    
    const updateWorldField = useCallback(function (field: WorldTextField, value: string): void {
        setWorlds(function (prev: WorldProps[]): WorldProps[] {
            const updated: WorldProps[] = [...prev];
            updated[selectedWorldIndex][field] = value;
            return updated;
        });
    }, [selectedWorldIndex]);
    
    const updateWorldArrayField = useCallback(function (field: WorldElementSection, value: WorldElement[]): void {
        setWorlds(function (prev: WorldProps[]): WorldProps[] {
            const updated: WorldProps[] = [...prev];
            updated[selectedWorldIndex][field] = value;
            return updated;
        });
    }, [selectedWorldIndex]);
    
    const toggleTool = useCallback(async function (enabled: boolean): Promise<void> {
        if (isSeriesMode) return;
        try {
            let response: boolean;
            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                response = await tauri.updateBookToolSetting(book?.bookId ?? '', 'worlds', enabled);
            } else {
                response = await apiPatch<boolean>('book/tool-setting', {
                    bookId: book?.bookId,
                    toolName: 'worlds',
                    enabled: enabled
                }, userToken, lang);
            }
            if (response && setBook && book) {
                setToolEnabled(enabled);
                setBook({
                    ...book,
                    tools: {
                        characters: book.tools?.characters ?? false,
                        worlds: enabled,
                        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]);
    
    const addNewWorld = useCallback(async function (): Promise<void> {
        if (newWorldName.trim() === '') {
            errorMessage(t("worldSetting.newWorldNameError"));
            return;
        }
        try {
            let newWorldId: string;
            if (isSeriesMode) {
                newWorldId = await apiPost<string>(
                    'series/world/add',
                    {
                        seriesId: entityId,
                        name: newWorldName,
                    },
                    userToken,
                    lang
                );
                if (!newWorldId) {
                    errorMessage(t("worldSetting.addWorldError"));
                    return;
                }
            } else if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                newWorldId = await tauri.addWorld(entityId, newWorldName);
                if (!newWorldId) {
                    errorMessage(t("worldSetting.addWorldError"));
                    return;
                }
            } else {
                newWorldId = await apiPost<string>('book/world/add', {
                    worldName: newWorldName,
                    bookId: entityId,
                }, userToken, lang);
                if (!newWorldId) {
                    errorMessage(t("worldSetting.addWorldError"));
                    return;
                }
            }
            const newWorld: WorldProps = {
                ...initialWorldState,
                id: newWorldId,
                name: newWorldName,
            };
            setWorlds(function (prev: WorldProps[]): WorldProps[] {
                return [...prev, newWorld];
            });
            setWorldsSelector(function (prev: SelectBoxProps[]): SelectBoxProps[] {
                return [...prev, {label: newWorldName, value: newWorldId}];
            });
            setNewWorldName('');
            setShowAddNewWorld(false);
            // Sélectionner le nouveau monde et passer en mode edit
            setSelectedWorldIndex(worlds.length); // Le nouveau monde est à la fin
            setViewMode('edit');
            setWorldBackup(null);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("worldSetting.unknownError"));
            }
        }
    }, [newWorldName, isSeriesMode, entityId, userToken, lang, errorMessage, t]);
    
    const saveWorld = useCallback(async function (): Promise<void> {
        if (worlds.length === 0) return;
        try {
            const currentWorld: WorldProps = worlds[selectedWorldIndex];
            if (isSeriesMode) {
                const response: boolean = await apiPatch<boolean>('series/world/update', {
                    worldId: currentWorld.id,
                    name: currentWorld.name,
                    history: currentWorld.history,
                    politics: currentWorld.politics,
                    economy: currentWorld.economy,
                    religion: currentWorld.religion,
                    languages: currentWorld.languages,
                }, userToken, lang);
                if (!response) {
                    errorMessage(t("worldSetting.updateWorldError"));
                    return;
                }
            } else if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                const response: boolean = await tauri.updateWorld(currentWorld);
                if (!response) {
                    errorMessage(t("worldSetting.updateWorldError"));
                    return;
                }
            } else {
                const response: boolean = await apiPatch<boolean>('book/world/update', {
                    world: currentWorld,
                    bookId: entityId,
                }, userToken, lang);
                if (!response) {
                    errorMessage(t("worldSetting.updateWorldError"));
                    return;
                }
            }
            successMessage(t("worldSetting.updateWorldSuccess"));
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("worldSetting.unknownError"));
            }
        }
    }, [worlds, selectedWorldIndex, isSeriesMode, entityId, userToken, lang, errorMessage, successMessage, t]);
    
    const exportToSeries = useCallback(async function (): Promise<void> {
        const selectedWorld: WorldProps | undefined = worlds[selectedWorldIndex];
        if (!selectedWorld || !bookSeriesId) return;
        
        try {
            const seriesWorldId: string = await apiPost<string>('series/world/add', {
                seriesId: bookSeriesId,
                world: {
                    name: selectedWorld.name,
                    history: selectedWorld.history || null,
                    politics: selectedWorld.politics || null,
                    economy: selectedWorld.economy || null,
                    religion: selectedWorld.religion || null,
                    languages: selectedWorld.languages || null,
                }
            }, userToken, lang);
            
            if (seriesWorldId) {
                const updateResponse: boolean = await apiPost<boolean>('book/world/update', {
                    world: {
                        ...selectedWorld,
                        seriesWorldId: seriesWorldId
                    },
                }, userToken, lang);
                
                if (updateResponse) {
                    setWorlds(function (prev: WorldProps[]): WorldProps[] {
                        const updated: WorldProps[] = [...prev];
                        updated[selectedWorldIndex] = {...selectedWorld, seriesWorldId: seriesWorldId};
                        return updated;
                    });
                    const newSeriesWorld: SeriesWorldProps = {
                        id: seriesWorldId,
                        name: selectedWorld.name,
                        history: selectedWorld.history || '',
                        politics: selectedWorld.politics || '',
                        economy: selectedWorld.economy || '',
                        religion: selectedWorld.religion || '',
                        languages: selectedWorld.languages || '',
                        laws: [],
                        biomes: [],
                        issues: [],
                        customs: [],
                        kingdoms: [],
                        climate: [],
                        resources: [],
                        wildlife: [],
                        arts: [],
                        ethnicGroups: [],
                        socialClasses: [],
                        importantCharacters: [],
                    };
                    setSeriesWorlds(function (prev: SeriesWorldProps[]): SeriesWorldProps[] {
                        return [...prev, newSeriesWorld];
                    });
                    successMessage(t("worldSetting.exportSuccess"));
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [worlds, selectedWorldIndex, bookSeriesId, userToken, lang, successMessage, errorMessage, t]);
    
    const importFromSeries = useCallback(async function (seriesWorldId: string): Promise<void> {
        const seriesWorld: SeriesWorldProps | undefined = seriesWorlds.find(function (w: SeriesWorldProps): boolean {
            return w.id === seriesWorldId;
        });
        if (!seriesWorld) return;
        
        try {
            let worldId: string;
            if (isDesktop && (isCurrentlyOffline() || book?.localBook)) {
                worldId = await tauri.addWorld(entityId, seriesWorld.name, undefined, seriesWorldId);
            } else {
                worldId = await apiPost<string>('book/world/add', {
                    worldName: seriesWorld.name,
                    bookId: entityId,
                    seriesWorldId: seriesWorldId,
                }, userToken, lang);
            }
            
            if (!worldId) {
                errorMessage(t("worldSetting.importError"));
                return;
            }
            
            const newWorld: WorldProps = {
                id: worldId,
                name: seriesWorld.name,
                history: seriesWorld.history || '',
                politics: seriesWorld.politics || '',
                economy: seriesWorld.economy || '',
                religion: seriesWorld.religion || '',
                languages: seriesWorld.languages || '',
                laws: [],
                biomes: [],
                issues: [],
                customs: [],
                kingdoms: [],
                climate: [],
                resources: [],
                wildlife: [],
                arts: [],
                ethnicGroups: [],
                socialClasses: [],
                importantCharacters: [],
                seriesWorldId: seriesWorldId,
            };
            setWorlds(function (prev: WorldProps[]): WorldProps[] {
                return [...prev, newWorld];
            });
            setWorldsSelector(function (prev: SelectBoxProps[]): SelectBoxProps[] {
                return [...prev, {label: seriesWorld.name, value: worldId}];
            });
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            }
        }
    }, [seriesWorlds, entityId, userToken, lang, errorMessage, t]);
    
    const getSeriesWorldForCurrentWorld = useCallback(function (): SeriesWorldProps | null {
        const currentWorld: WorldProps | undefined = worlds[selectedWorldIndex];
        if (!currentWorld?.seriesWorldId) return null;
        return seriesWorlds.find(function (world: SeriesWorldProps): boolean {
            return world.id === currentWorld.seriesWorldId;
        }) || null;
    }, [worlds, selectedWorldIndex, seriesWorlds]);
    
    // Navigation functions
    const enterDetailMode = useCallback(function (worldId: string): void {
        const index: number = worlds.findIndex(function (world: WorldProps): boolean {
            return world.id === worldId;
        });
        if (index !== -1) {
            setSelectedWorldIndex(index);
            setViewMode('detail');
            setWorldBackup(null);
        }
    }, [worlds]);
    
    const enterEditMode = useCallback(function (): void {
        if (worlds.length > 0 && selectedWorldIndex >= 0) {
            setWorldBackup({...worlds[selectedWorldIndex]});
        }
        setViewMode('edit');
    }, [worlds, selectedWorldIndex]);
    
    const exitEditMode = useCallback(async function (save: boolean): Promise<void> {
        if (save) {
            await saveWorld();
            if (worldBackup) {
                setViewMode('detail');
            } else {
                setViewMode('list');
            }
        } else {
            if (worldBackup && selectedWorldIndex >= 0) {
                setWorlds(function (prev: WorldProps[]): WorldProps[] {
                    const updated: WorldProps[] = [...prev];
                    updated[selectedWorldIndex] = worldBackup;
                    return updated;
                });
                setViewMode('detail');
            } else {
                setViewMode('list');
            }
        }
        setWorldBackup(null);
    }, [saveWorld, worldBackup, selectedWorldIndex]);
    
    const backToList = useCallback(function (): void {
        setSelectedWorldIndex(0);
        setWorldBackup(null);
        setViewMode('list');
    }, []);
    
    return {
        // State
        worlds,
        seriesWorlds,
        selectedWorldIndex,
        worldsSelector,
        toolEnabled,
        isLoading,
        isSeriesMode,
        bookSeriesId,
        showAddNewWorld,
        newWorldName,
        
        // Navigation state
        viewMode,
        worldBackup,
        
        // Actions
        selectWorld,
        addNewWorld,
        saveWorld,
        updateWorldField,
        updateWorldArrayField,
        toggleTool,
        importFromSeries,
        exportToSeries,
        refreshWorlds,
        refreshSeriesWorlds,
        setShowAddNewWorld,
        setNewWorldName,
        setWorlds,
        getSeriesWorldForCurrentWorld,
        
        // Navigation actions
        enterDetailMode,
        enterEditMode,
        exitEditMode,
        backToList,
    };
}
