'use client'
import {ChangeEvent, forwardRef, useContext, useEffect, useImperativeHandle, useState} from 'react';
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faPlus, IconDefinition} from "@fortawesome/free-solid-svg-icons";
import {WorldContext} from '@/context/WorldContext';
import {BookContext} from "@/context/BookContext";
import {AlertContext} from "@/context/AlertContext";
import {SelectBoxProps} from "@/shared/interface";
import System from "@/lib/models/System";
import {elementSections, WorldProps} from "@/lib/models/World";
import {SessionContext} from "@/context/SessionContext";
import InputField from "@/components/form/InputField";
import TextInput from '@/components/form/TextInput';
import TexteAreaInput from "@/components/form/TexteAreaInput";
import WorldElementComponent from './WorldElement';
import SelectBox from "@/components/form/SelectBox";
import {useTranslations} from "next-intl";
import {LangContext, LangContextProps} from "@/context/LangContext";
import OfflineContext, {OfflineContextType} from "@/context/OfflineContext";

export interface ElementSection {
    title: string;
    section: keyof WorldProps;
    icon: IconDefinition;
}

export function WorldSetting(props: any, ref: any) {
    const t = useTranslations();
    const {lang} = useContext<LangContextProps>(LangContext);
    const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
    const {errorMessage, successMessage} = useContext(AlertContext);
    const {session} = useContext(SessionContext);
    const {book} = useContext(BookContext);
    const bookId: string = book?.bookId ? book.bookId.toString() : '';
    
    const [worlds, setWorlds] = useState<WorldProps[]>([]);
    const [newWorldName, setNewWorldName] = useState<string>('');
    const [selectedWorldIndex, setSelectedWorldIndex] = useState<number>(0);
    const [worldsSelector, setWorldsSelector] = useState<SelectBoxProps[]>([]);
    const [showAddNewWorld, setShowAddNewWorld] = useState<boolean>(false);
    
    useImperativeHandle(ref, function () {
        return {
            handleSave: handleUpdateWorld,
        };
    });
    
    useEffect((): void => {
        getWorlds().then();
    }, []);
    
    async function getWorlds() {
        try {
            let response: WorldProps[];
            if (isCurrentlyOffline()) {
                response = await window.electron.invoke<WorldProps[]>('db:book:worlds:get', {bookid: bookId});
            } else {
                response = await System.authGetQueryToServer<WorldProps[]>(`book/worlds`, session.accessToken, lang, {
                    bookid: bookId,
                });
            }
            if (response) {
                setWorlds(response);
                const formattedWorlds: SelectBoxProps[] = response.map(
                    (world: WorldProps): SelectBoxProps => ({
                        label: world.name,
                        value: world.id.toString(),
                    }),
                );
                setWorldsSelector(formattedWorlds);
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("worldSetting.unknownError"))
            }
        }
    }
    
    async function handleAddNewWorld(): Promise<void> {
        if (newWorldName.trim() === '') {
            errorMessage(t("worldSetting.newWorldNameError"));
            return;
        }
        try {
            let worldId: string;
            if (isCurrentlyOffline()) {
                worldId = await window.electron.invoke<string>('db:book:world:add', {
                    worldName: newWorldName,
                    bookId: bookId,
                });
            } else {
                worldId = await System.authPostToServer<string>('book/world/add', {
                    worldName: newWorldName,
                    bookId: bookId,
                }, session.accessToken, lang);
            }
            if (!worldId) {
                errorMessage(t("worldSetting.addWorldError"));
                return;
            }
            const newWorldId: string = worldId;
            const newWorld: WorldProps = {
                id: newWorldId,
                name: newWorldName,
                history: '',
                politics: '',
                economy: '',
                religion: '',
                languages: '',
                laws: [],
                biomes: [],
                issues: [],
                customs: [],
                kingdoms: [],
                climate: [],
                resources: [],
                wildlife: [],
                arts: [],
                ethnicGroups: [],
                socialClasses: [],
                importantCharacters: [],
            };
            setWorlds([...worlds, newWorld]);
            setWorldsSelector([
                ...worldsSelector,
                {label: newWorldName, value: newWorldId.toString()},
            ]);
            setNewWorldName('');
            setShowAddNewWorld(false);
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t("worldSetting.unknownError"))
            }
        }
    }
    
    async function handleUpdateWorld(): Promise<void> {
        try {
            let response: boolean;
            if (isCurrentlyOffline()) {
                response = await window.electron.invoke<boolean>('db:book:world:update', {
                    world: worlds[selectedWorldIndex],
                    bookId: bookId,
                });
            } else {
                response = await System.authPutToServer<boolean>('book/world/update', {
                    world: worlds[selectedWorldIndex],
                    bookId: bookId,
                }, session.accessToken, 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"))
            }
        }
    }
    
    function handleInputChange(value: string, field: keyof WorldProps) {
        const updatedWorlds = [...worlds] as WorldProps[];
        (updatedWorlds[selectedWorldIndex][field] as string) = value;
        setWorlds(updatedWorlds);
    }
    
    return (
        <div className="space-y-6">
            <div className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-lg">
                <div className="grid grid-cols-1 gap-4 mb-4">
                    <InputField
                        fieldName={t("worldSetting.selectWorld")}
                        input={
                            <SelectBox
                                onChangeCallBack={(e) => {
                                    const worldId = e.target.value;
                                    const index = worlds.findIndex(world => world.id.toString() === worldId);
                                    if (index !== -1) {
                                        setSelectedWorldIndex(index);
                                    }
                                }}
                                data={worldsSelector.length > 0 ? worldsSelector : [{
                                    label: t("worldSetting.noWorldAvailable"),
                                    value: '0'
                                }]}
                                defaultValue={worlds[selectedWorldIndex]?.id.toString() || '0'}
                                placeholder={t("worldSetting.selectWorldPlaceholder")}
                            />
                        }
                        actionIcon={faPlus}
                        actionLabel={t("worldSetting.addWorldLabel")}
                        action={async () => setShowAddNewWorld(!showAddNewWorld)}
                    />
                    
                    {showAddNewWorld && (
                        <InputField
                            input={
                                <TextInput
                                    value={newWorldName}
                                    setValue={(e: ChangeEvent<HTMLInputElement>) => setNewWorldName(e.target.value)}
                                    placeholder={t("worldSetting.newWorldPlaceholder")}
                                />
                            }
                            actionIcon={faPlus}
                            actionLabel={t("worldSetting.createWorldLabel")}
                            addButtonCallBack={handleAddNewWorld}
                        />
                    )}
                </div>
            </div>
            
            {worlds.length > 0 && worlds[selectedWorldIndex] ? (
                <WorldContext.Provider value={{worlds, setWorlds, selectedWorldIndex}}>
                    <div
                        className="bg-tertiary/90 backdrop-blur-sm rounded-xl p-5 border border-secondary/50 shadow-lg">
                        <div className="mb-4">
                            <InputField
                                fieldName={t("worldSetting.worldName")}
                                input={
                                    <TextInput
                                        value={worlds[selectedWorldIndex].name}
                                        setValue={(e: ChangeEvent<HTMLInputElement>) => {
                                            const updatedWorlds: WorldProps[] = [...worlds];
                                            updatedWorlds[selectedWorldIndex].name = e.target.value
                                            setWorlds(updatedWorlds);
                                        }}
                                        placeholder={t("worldSetting.worldNamePlaceholder")}
                                    />
                                }
                            />
                        </div>
                        <InputField
                            fieldName={t("worldSetting.worldHistory")}
                            input={
                                <TexteAreaInput
                                    value={worlds[selectedWorldIndex].history || ''}
                                    setValue={(e) => handleInputChange(e.target.value, 'history')}
                                    placeholder={t("worldSetting.worldHistoryPlaceholder")}
                                />
                            }
                        />
                    </div>
                    
                    <div
                        className="bg-tertiary/90 backdrop-blur-sm rounded-xl shadow-lg p-4 border border-secondary/50">
                        <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
                            <InputField
                                fieldName={t("worldSetting.politics")}
                                input={
                                    <TexteAreaInput
                                        value={worlds[selectedWorldIndex].politics || ''}
                                        setValue={(e) => handleInputChange(e.target.value, 'politics')}
                                        placeholder={t("worldSetting.politicsPlaceholder")}
                                    />
                                }
                            />
                            <InputField
                                fieldName={t("worldSetting.economy")}
                                input={
                                    <TexteAreaInput
                                        value={worlds[selectedWorldIndex].economy || ''}
                                        setValue={(e) => handleInputChange(e.target.value, 'economy')}
                                        placeholder={t("worldSetting.economyPlaceholder")}
                                    />
                                }
                            />
                        </div>
                    </div>
                    
                    <div
                        className="bg-tertiary/90 backdrop-blur-sm rounded-xl shadow-lg p-4 border border-secondary/50">
                        <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
                            <InputField
                                fieldName={t("worldSetting.religion")}
                                input={
                                    <TexteAreaInput
                                        value={worlds[selectedWorldIndex].religion || ''}
                                        setValue={(e) => handleInputChange(e.target.value, 'religion')}
                                        placeholder={t("worldSetting.religionPlaceholder")}
                                    />
                                }
                            />
                            <InputField
                                fieldName={t("worldSetting.languages")}
                                input={
                                    <TexteAreaInput
                                        value={worlds[selectedWorldIndex].languages || ''}
                                        setValue={(e) => handleInputChange(e.target.value, 'languages')}
                                        placeholder={t("worldSetting.languagesPlaceholder")}
                                    />
                                }
                            />
                        </div>
                    </div>
                    
                    {elementSections.map((section, index) => (
                        <div key={index}
                             className="bg-tertiary/90 backdrop-blur-sm rounded-xl shadow-lg p-4 border border-secondary/50">
                            <h3 className="text-lg font-semibold text-text-primary mb-4 flex items-center">
                                <FontAwesomeIcon icon={section.icon} className="mr-2 w-5 h-5"/>
                                {section.title}
                                <span
                                    className="ml-2 text-sm bg-dark-background text-text-secondary py-0.5 px-2 rounded-full">
                                    {worlds[selectedWorldIndex][section.section]?.length || 0}
                                </span>
                            </h3>
                            <WorldElementComponent
                                sectionLabel={section.title}
                                sectionType={section.section}
                            />
                        </div>
                    ))}
                </WorldContext.Provider>
            ) : (
                <div
                    className="bg-tertiary/90 backdrop-blur-sm rounded-xl shadow-lg p-8 border border-secondary/50 text-center">
                    <p className="text-text-secondary mb-4">{t("worldSetting.noWorldAvailable")}</p>
                </div>
            )}
        </div>
    );
}

export default forwardRef(WorldSetting);