import { useCallback, useContext, useMemo } from "preact/hooks";
import { useBool } from "@common/hooks/useBool";
import { Modal } from "@common/components/modal/Modal";
import { useInputCallback } from "@common/hooks/useInputCallback";

import { DEFAULT_STORY, StateContext } from "../../contexts/state";
import { LLMContext } from "../../contexts/llm";
import { MiniChat } from "../minichat/minichat";
import { AutoTextarea } from "../autoTextarea";
import { Ace } from "../ace";
import { ConnectionEditor } from "./connectionEditor";

import styles from './header.module.css';

export const Header = () => {
    const { contextLength, promptTokens, modelName, spentKudos, hasToolCalls } = useContext(LLMContext);
    const {
        messages,
        connection,
        systemPrompt,
        lore,
        userPrompt,
        bannedWords,
        summarizePrompt,
        summaryEnabled,
        totalSpentKudos,
        stories,
        currentStory,
        setSystemPrompt,
        setLore,
        setUserPrompt,
        addSwipe,
        setBannedWords,
        setInstruct,
        setSummarizePrompt,
        setSummaryEnabled,
        setConnection,
        setCurrentStory,
        createStory,
        deleteStory,
    } = useContext(StateContext);

    const connectionsOpen = useBool();
    const loreOpen = useBool();
    const promptsOpen = useBool();
    const genparamsOpen = useBool();
    const assistantOpen = useBool();
    const isOnline = useMemo(() => contextLength > 0, [contextLength]);

    const bannedWordsInput = useMemo(() => bannedWords.join('\n'), [bannedWords]);

    const handleAssistantAddSwipe = useCallback((answer: string) => {
        const index = messages.findLastIndex(m => m.role === 'assistant');
        addSwipe(index, answer);
        assistantOpen.setFalse();
    }, [addSwipe, messages]);

    const handleSetBannedWords = useInputCallback((text) => {
        const words = text.split('\n');
        setBannedWords(words);
    }, [setBannedWords]);

    const handleBlurBannedWords = useInputCallback((text) => {
        const words = text.toLowerCase().split('\n').sort();
        setBannedWords(words);
    }, [setBannedWords]);

    const handleSetSummaryEnabled = useCallback((e: Event) => {
        if (e.target instanceof HTMLInputElement) {
            setSummaryEnabled(e.target.checked);
        }
    }, [setSummaryEnabled]);

    const handleChangeStory = useInputCallback((story) => {
        setCurrentStory(story);
    }, []);

    const handleDeleteStory = useCallback(() => {
        if (confirm(`Delete story "${currentStory}"?`)) {
            deleteStory(currentStory);
        }
    }, [currentStory]);

    const handleDuplicateStory = useCallback(() => {
        const id = prompt('Story id');
        if (id) {
            createStory(id, currentStory);
            setCurrentStory(id);
        }
    }, [currentStory]);

    return (
        <div class={styles.header}>
            <div class={styles.inputs}>
                <div class={styles.buttons}>
                    <button class={`icon ${isOnline ? styles.online : styles.offline}`} onClick={connectionsOpen.setTrue} title='Connection settings'>
                        🔌
                    </button>
                </div>
                <div class={styles.info}>
                    <span class={styles.notImportant}>{modelName}</span>
                    <span>📃{promptTokens}/{contextLength}</span>
                    {connection.type === 'horde' ? <>
                        <span class={styles.notImportant}>💲{spentKudos}</span>
                        <span class={styles.notImportant}>💰{totalSpentKudos}</span>
                    </> : null}
                </div>
            </div>
            <div class={styles.buttons}>
                <button class='icon color' title='Edit lore' onClick={loreOpen.setTrue}>
                    🌍
                </button>
                <button class='icon color' title='Generation parameters' onClick={genparamsOpen.setTrue}>
                    ⚙
                </button>
                <button class='icon color' title='Edit prompts' onClick={promptsOpen.setTrue}>
                    📃
                </button>
            </div>
            <div class={styles.buttons}>
                <button class='icon' onClick={assistantOpen.setTrue} title='Ask assistant'>
                    ❓
                </button>
            </div>
            <Modal open={connectionsOpen.value} onClose={connectionsOpen.setFalse}>
                <h3 class={styles.modalTitle}>Connection settings</h3>
                <ConnectionEditor connection={connection} setConnection={setConnection} />
            </Modal>
            <Modal open={loreOpen.value} onClose={loreOpen.setFalse} class={styles.modal}>
                <h3 class={styles.modalTitle}>Lore Editor</h3>
                <div class={styles.currentStory}>
                    <select value={currentStory} onChange={handleChangeStory} class={styles.storiesSelector}>
                        {Object.keys(stories).map((story) => (
                            <option key={story} value={story}>{story}</option>
                        ))}
                    </select>
                    <button class='icon' onClick={handleDuplicateStory}>
                        ➕
                    </button>
                    {currentStory !== DEFAULT_STORY
                        ? <button class='icon' onClick={handleDeleteStory}>
                            🗑️
                        </button>
                        : null}
                </div>
                <AutoTextarea
                    value={lore}
                    onInput={setLore}
                    placeholder="Describe your world, for example: World of Awoo has big mountains and wide rivers."
                    class={styles.loreText}
                />
            </Modal>
            <Modal open={genparamsOpen.value} onClose={genparamsOpen.setFalse} class={styles.modal}>
                <h3 class={styles.modalTitle}>Generation Parameters</h3>
                <div className={styles.scrollPane}>
                    <h4 class={styles.modalTitle}>Banned phrases</h4>
                    <AutoTextarea
                        placeholder="Each phrase on separate line"
                        value={bannedWordsInput}
                        onInput={handleSetBannedWords}
                        onBlur={handleBlurBannedWords}
                        class={styles.template}
                    />
                </div>
            </Modal>
            <Modal open={promptsOpen.value} onClose={promptsOpen.setFalse}>
                <h3 class={styles.modalTitle}>Prompts Editor</h3>
                <div className={styles.scrollPane}>
                    <h4 class={styles.modalTitle}>System prompt</h4>
                    <AutoTextarea value={systemPrompt} onInput={setSystemPrompt} />
                    <hr />
                    <h4 class={styles.modalTitle}>User prompt template</h4>
                    <Ace value={userPrompt} onInput={setUserPrompt} />
                    <hr />
                    <h4 class={styles.modalTitle}>Summary template</h4>
                    <Ace value={summarizePrompt} onInput={setSummarizePrompt} />
                    <label>
                        <input type='checkbox' checked={summaryEnabled} onChange={handleSetSummaryEnabled} />
                        &nbsp;Enable summarization
                    </label>
                    <hr />
                    <h4 class={styles.modalTitle}>
                        Instruct template
                        {hasToolCalls && <small> (tool calls)</small>}
                    </h4>
                    <Ace value={connection.instruct} onInput={setInstruct} />
                </div>
            </Modal>
            <MiniChat
                history={messages}
                open={assistantOpen.value}
                onClose={assistantOpen.setFalse}
                buttons={{ 'Add swipe': handleAssistantAddSwipe }}
            />
        </div>
    );
}