'use client'
import React, {lazy, Suspense, useContext, useRef, useState} from 'react';
import {Save} from 'lucide-react';
import {useTranslations} from '@/lib/i18n';
import SectionHeader from "@/components/ui/SectionHeader";
import IconButton from "@/components/ui/IconButton";
import PulseLoader from '@/components/ui/PulseLoader';
import ToggleSwitch from "@/components/form/ToggleSwitch";
import {BookContext, BookContextProps} from "@/context/BookContext";
import {SessionContext, SessionContextProps} from "@/context/SessionContext";
import {AlertContext, AlertContextProps} from "@/context/AlertContext";
import {LangContext, LangContextProps} from "@/context/LangContext";
import OfflineContext, {OfflineContextType} from "@/context/OfflineContext";
import {isDesktop} from "@/lib/configs";
import {apiPatch} from "@/lib/api/client";
import {updateBookToolSetting} from "@/lib/tauri";
import {SettingRef} from "@/lib/types/settings";
import {BookProps} from "@/lib/types/book";

const BasicInformationSetting = lazy(function () {
    return import('./BasicInformationSetting');
});
const GuideLineSetting = lazy(function () {
    return import('./guideline/GuideLineSetting');
});
const StorySetting = lazy(function () {
    return import('./story/StorySetting');
});
const QuillSenseSetting = lazy(function () {
    return import('./quillsense/QuillSenseSetting');
});
const WorldSettings = lazy(function () {
    return import('./world/settings/WorldSettings');
});
const LocationSettings = lazy(function () {
    return import('./locations/settings/LocationSettings');
});
const CharacterSettings = lazy(function () {
    return import('./characters/settings/CharacterSettings');
});
const SpellSettings = lazy(function () {
    return import('./spells/settings/SpellSettings');
});
const ExportSetting = lazy(function () {
    return import('./ExportSetting');
});

interface BookSettingOptionProps {
    setting: string;
}

const selfManagedSettings: string[] = ['characters', 'spells', 'world', 'worlds', 'locations', 'export'];

type ToolName = 'worlds' | 'locations' | 'characters' | 'spells' | 'quillsense';

const toggleableSettings: Record<string, ToolName> = {
    'world': 'worlds',
    'worlds': 'worlds',
    'locations': 'locations',
    'characters': 'characters',
    'spells': 'spells',
    'quillsense': 'quillsense',
};

function getInitialToolEnabled(setting: string, book: BookProps | null): boolean {
    const toolName: ToolName | undefined = toggleableSettings[setting];
    if (!toolName) return false;
    if (toolName === 'quillsense') return book?.quillsenseEnabled ?? false;
    return book?.tools?.[toolName] ?? false;
}

export default function BookSettingOption({setting}: BookSettingOptionProps): React.JSX.Element {
    const t = useTranslations();
    const settingRef: React.RefObject<SettingRef | null> = useRef<SettingRef>(null);
    const {book, setBook}: BookContextProps = useContext<BookContextProps>(BookContext);
    const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
    const {errorMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
    const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
    const {isCurrentlyOffline} = useContext(OfflineContext);
    const userToken: string = session?.accessToken ?? '';
    
    const isToggleable: boolean = setting in toggleableSettings;
    const [toolEnabled, setToolEnabled] = useState<boolean>(getInitialToolEnabled(setting, book));

    const showSaveButton: boolean = !selfManagedSettings.includes(setting);

    function renderTitle(): string {
        switch (setting) {
            case 'basic-information':
                return t("bookSettingOption.basicInformation");
            case 'guide-line':
                return t("bookSettingOption.guideLine");
            case 'story':
                return t("bookSettingOption.storyPlan");
            case 'quillsense':
                return t("bookSettingOption.quillsense");
            case 'world':
                return t("bookSettingOption.manageWorlds");
            case 'locations':
                return t("bookSettingOption.yourLocations");
            case 'characters':
                return t("bookSettingOption.characters");
            case 'spells':
                return t("bookSettingOption.spells");
            case 'export':
                return t("bookSettingOption.export");
            default:
                return "";
        }
    }
    
    async function handleToggleTool(enabled: boolean): Promise<void> {
        const toolName: ToolName | undefined = toggleableSettings[setting];
        if (!toolName || !book?.bookId) return;
        const useLocal: boolean = isDesktop && (isCurrentlyOffline() || !!book.localBook);
        if (useLocal && toolName === 'quillsense') {
            errorMessage(t('bookSettingOption.quillsenseOffline'));
            return;
        }
        try {
            const result: boolean = useLocal
                ? await updateBookToolSetting(book.bookId, toolName, enabled)
                : await apiPatch<boolean>('book/tool-setting', {
                    bookId: book.bookId,
                    toolName: toolName,
                    enabled: enabled
                }, userToken, lang);
            if (result && setBook && book) {
                setToolEnabled(enabled);
                if (toolName === 'quillsense') {
                    setBook({...book, quillsenseEnabled: enabled});
                } else {
                    setBook({
                        ...book,
                        tools: {
                            characters: toolName === 'characters' ? enabled : (book.tools?.characters ?? false),
                            worlds: toolName === 'worlds' ? enabled : (book.tools?.worlds ?? false),
                            locations: toolName === 'locations' ? enabled : (book.tools?.locations ?? false),
                            spells: toolName === 'spells' ? enabled : (book.tools?.spells ?? false),
                        }
                    });
                }
            }
        } catch (e: unknown) {
            if (e instanceof Error) {
                errorMessage(e.message);
            } else {
                errorMessage(t('bookSettingOption.unknownError'));
            }
        }
    }

    async function handleSaveClick(): Promise<void> {
        if (settingRef.current?.handleSave) {
            await settingRef.current.handleSave();
        }
    }
    
    function renderHeaderActions(): React.JSX.Element {
        return (
            <div className="flex items-center gap-3">
                {isToggleable && (
                    <ToggleSwitch
                        checked={toolEnabled}
                        onChange={handleToggleTool}
                        size="sm"
                    />
                )}
                {showSaveButton && (
                    <IconButton icon={Save} variant="primary" onClick={handleSaveClick}/>
                )}
            </div>
        );
    }

    return (
        <div className="px-6">
            <div className="sticky top-0 z-10 bg-darkest-background pt-6 pb-4">
                <SectionHeader
                    title={renderTitle()}
                    actions={renderHeaderActions()}
                />
            </div>
            <div className="mb-6">
                <Suspense fallback={<PulseLoader/>}>
                    {setting === 'basic-information' && <BasicInformationSetting ref={settingRef}/>}
                    {setting === 'guide-line' && <GuideLineSetting ref={settingRef}/>}
                    {setting === 'story' && <StorySetting ref={settingRef}/>}
                    {setting === 'quillsense' && <QuillSenseSetting ref={settingRef} toolEnabled={toolEnabled}/>}
                    {(setting === 'world' || setting === 'worlds') && (
                        <WorldSettings entityType="book" toolEnabled={toolEnabled}/>
                    )}
                    {setting === 'locations' && (
                        <LocationSettings entityType="book" toolEnabled={toolEnabled}/>
                    )}
                    {setting === 'characters' && (
                        <CharacterSettings entityType="book" toolEnabled={toolEnabled}/>
                    )}
                    {setting === 'spells' && (
                        <SpellSettings entityType="book" toolEnabled={toolEnabled}/>
                    )}
                    {setting === 'export' && <ExportSetting/>}
                    {!['basic-information', 'guide-line', 'story', 'world', 'worlds', 'locations', 'characters', 'spells', 'quillsense', 'export'].includes(setting) && (
                        <div className="text-text-secondary py-4 text-center">
                            {t("bookSettingOption.notAvailable")}
                        </div>
                    )}
                </Suspense>
            </div>
        </div>
    );
}
