import { useBool } from "@common/hooks/useBool";
import { useInputState } from "@common/hooks/useInputState";
import clsx from "clsx";
import { ChevronDown, ChevronRight, Copy, Download, Globe, MessageSquarePlus, MessagesSquare, Pencil, Plus, Settings, Upload, X } from "lucide-preact";
import styles from '../assets/menu.module.css';
import type { Story, World } from "../contexts/state";
import { isStory, isWorld, useAppState } from "../contexts/state";
import CharacterCard from "../utils/character-card";
import { SettingsModal } from "./settings-modal";
import Prompt from "../utils/prompt";

// ─── Inline Rename Input ──────────────────────────────────────────────────────

interface RenameInputProps {
    value: string;
    onSubmit: (title: string) => void;
    onCancel: () => void;
    className?: string;
}

const RenameInput = ({ value, onSubmit, onCancel, className }: RenameInputProps) => {
    const [editTitle, setEditTitle] = useInputState(value);

    const handleSubmit = () => {
        if (editTitle.trim()) onSubmit(editTitle.trim());
        else onCancel();
    };

    const handleKeyDown = (e: KeyboardEvent) => {
        if (e.key === 'Enter') handleSubmit();
        else if (e.key === 'Escape') onCancel();
    };

    return (
        <input
            class={clsx(styles.input, className)}
            value={editTitle}
            onInput={setEditTitle}
            onKeyDown={handleKeyDown}
            onBlur={handleSubmit}
            autoFocus
        />
    );
};

// ─── Story Item ───────────────────────────────────────────────────────────────

interface StoryItemProps {
    story: Story;
    active: boolean;
    onSelect: () => void;
    onRename: (newTitle: string) => void;
    onDelete: () => void;
    onDuplicate: () => void;
    onExport: () => void;
}

const StoryItem = ({ story, active, onSelect, onRename, onDelete, onDuplicate, onExport }: StoryItemProps) => {
    const isEditing = useBool(false);
    const appState = useAppState();

    if (isEditing.value) {
        return (
            <div class={clsx(styles.itemWrapper, styles.storyItem, active && styles.active)}>
                <RenameInput
                    value={story.title}
                    onSubmit={(t) => { onRename(t); isEditing.setFalse(); }}
                    onCancel={isEditing.setFalse}
                />
            </div>
        );
    }

    return (
        <div class={clsx(styles.itemWrapper, styles.storyItem, active && styles.active)}>
            <button
                class={clsx(styles.item, active && styles.active)}
                onClick={onSelect}
                onDblClick={isEditing.setTrue}
            >
                {Prompt.substituteVars(appState, story.title)}
            </button>
            <div class={styles.actions}>
                <button class={styles.actionButton} onClick={isEditing.setTrue} title="Rename">
                    <Pencil size={14} />
                </button>
                <button class={styles.actionButton} onClick={onExport} title="Export Story">
                    <Download size={14} />
                </button>
                <button class={styles.actionButton} onClick={onDuplicate} title="Duplicate">
                    <Copy size={14} />
                </button>
                <button class={styles.actionButton} onClick={onDelete} title="Delete">
                    <X size={14} />
                </button>
            </div>
        </div>
    );
};

// ─── World Item ───────────────────────────────────────────────────────────────

interface WorldItemProps {
    world: World;
    activeWorldId: string | null;
    activeStoryId: string | null;
    onSelectWorld: () => void;
    onRenameWorld: (title: string) => void;
    onDeleteWorld: () => void;
    onExportWorld: () => void;
    onCreateStory: () => void;
    onSelectStory: (storyId: string) => void;
    onRenameStory: (storyId: string, title: string) => void;
    onDeleteStory: (storyId: string) => void;
    onDuplicateStory: (storyId: string) => void;
    onExportStory: (storyId: string) => void;
    onImportStory: () => void;
}

const WorldItem = ({
    world, activeWorldId, activeStoryId,
    onSelectWorld, onRenameWorld, onDeleteWorld, onExportWorld, onCreateStory,
    onSelectStory, onRenameStory, onDeleteStory, onDuplicateStory, onExportStory, onImportStory,
}: WorldItemProps) => {
    const isRenaming = useBool(false);
    const isExpanded = useBool(activeWorldId === world.id);

    const isWorldActive = activeWorldId === world.id && !activeStoryId;

    const toggleExpand = (e: MouseEvent) => {
        e.stopPropagation();
        isExpanded.toggle();
    };

    return (
        <div class={styles.worldGroup}>
            {isRenaming.value ? (
                <div class={clsx(styles.itemWrapper, isWorldActive && styles.active)}>
                    <RenameInput
                        value={world.title}
                        onSubmit={(t) => { onRenameWorld(t); isRenaming.setFalse(); }}
                        onCancel={isRenaming.setFalse}
                    />
                </div>
            ) : (
                <div class={clsx(styles.itemWrapper, isWorldActive && styles.active)} onClick={isExpanded.setTrue}>
                    <button class={styles.expandButton} onClick={toggleExpand} title={isExpanded.value ? 'Collapse' : 'Expand'}>
                        {isExpanded.value ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
                    </button>
                    <button
                        class={clsx(styles.item, styles.worldTitle, isWorldActive && styles.active)}
                        onClick={onSelectWorld}
                        onDblClick={isRenaming.setTrue}
                    >
                        {world.chatOnly ? <MessagesSquare size={13} /> : <Globe size={13} />}
                        {world.title}
                    </button>
                    <div class={styles.actions}>
                        <button class={styles.actionButton} onClick={onCreateStory} title={world.chatOnly ? "New Chat" : "New Story"}>
                            {world.chatOnly ? <MessageSquarePlus size={14} /> : <Plus size={14} />}
                        </button>
                        <button class={styles.actionButton} onClick={onImportStory} title="Import Story">
                            <Upload size={14} />
                        </button>
                        <button class={styles.actionButton} onClick={onExportWorld} title="Export World">
                            <Download size={14} />
                        </button>
                        <button class={styles.actionButton} onClick={isRenaming.setTrue} title="Rename">
                            <Pencil size={14} />
                        </button>
                        <button class={styles.actionButton} onClick={onDeleteWorld} title="Delete World">
                            <X size={14} />
                        </button>
                    </div>
                </div>
            )}
            {isExpanded.value && (
                <div class={styles.storiesList}>
                    {world.stories.map(story => (
                        <StoryItem
                            key={story.id}
                            story={story}
                            active={activeStoryId === story.id && activeWorldId === world.id}
                            onSelect={() => onSelectStory(story.id)}
                            onRename={(title) => onRenameStory(story.id, title)}
                            onDelete={() => onDeleteStory(story.id)}
                            onDuplicate={() => onDuplicateStory(story.id)}
                            onExport={() => onExportStory(story.id)}
                        />
                    ))}
                    {world.stories.length === 0 && (
                        <div class={styles.emptyStories}>No stories yet</div>
                    )}
                </div>
            )}
        </div>
    );
};

// ─── Menu Sidebar ─────────────────────────────────────────────────────────────

export const Menu = ({ visible }: { visible: boolean }) => {
    const { worlds, currentWorld, currentStory, dispatch } = useAppState();
    const isSettingsOpen = useBool(false);
    if (!visible) return null;

    const handleCreateWorld = () => {
        dispatch({ type: 'CREATE_WORLD', title: 'New World' });
    };

    const handleCreateChatWorld = () => {
        dispatch({ type: 'CREATE_WORLD', title: 'New Chat', chatOnly: true });
    };

    const handleSelectWorld = (worldId: string) => {
        dispatch({ type: 'SELECT_WORLD', worldId });
    };

    const handleRenameWorld = (worldId: string, title: string) => {
        dispatch({ type: 'RENAME_WORLD', worldId, title });
    };

    const handleDeleteWorld = (worldId: string) => {
        const world = worlds.find(w => w.id === worldId);
        if (!world) return;
        if (confirm(`Delete world "${world.title}" and all its stories?`)) {
            dispatch({ type: 'DELETE_WORLD', worldId });
        }
    };

    const handleCreateStory = (worldId: string) => {
        dispatch({ type: 'CREATE_STORY', worldId });
    };

    const handleSelectStory = (worldId: string, storyId: string) => {
        dispatch({ type: 'SELECT_STORY', worldId, id: storyId });
    };

    const handleRenameStory = (worldId: string, storyId: string, title: string) => {
        dispatch({ type: 'RENAME_STORY', worldId, id: storyId, title });
    };

    const handleDeleteStory = (worldId: string, storyId: string) => {
        const world = worlds.find(w => w.id === worldId);
        const story = world?.stories.find(s => s.id === storyId);
        if (!story) return;
        if (confirm(`Delete "${story.title}"?`)) {
            dispatch({ type: 'DELETE_STORY', worldId, id: storyId });
        }
    };

    const handleDuplicateStory = (worldId: string, storyId: string) => {
        dispatch({ type: 'DUPLICATE_STORY', worldId, id: storyId });
    };

    const handleExportWorld = (worldId: string) => {
        const world = worlds.find(w => w.id === worldId);
        if (!world) return;
        const json = JSON.stringify(world, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${world.title}.json`;
        a.click();
        URL.revokeObjectURL(url);
    };

    const handleExportStory = (worldId: string, storyId: string) => {
        const world = worlds.find(w => w.id === worldId);
        const story = world?.stories.find(s => s.id === storyId);
        if (!story) return;
        const json = JSON.stringify(story, null, 2);
        const blob = new Blob([json], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${story.title}.json`;
        a.click();
        URL.revokeObjectURL(url);
    };

    const handleImportStory = (worldId: string) => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json,application/json';
        input.onchange = () => {
            const file = input.files?.[0];
            if (!file) return;
            const reader = new FileReader();
            reader.onload = () => {
                try {
                    const parsed = JSON.parse(reader.result as string);
                    if (isStory(parsed)) {
                        dispatch({ type: 'IMPORT_STORY', worldId, story: parsed });
                    } else {
                        alert('Invalid story file.');
                    }
                } catch {
                    alert('Invalid file.');
                }
            };
            reader.readAsText(file);
        };
        input.click();
    };

    const handleImportWorld = () => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json,.png,application/json,image/png';
        input.onchange = async () => {
            const file = input.files?.[0];
            if (!file) return;
            if (file.name.endsWith('.png')) {
                const card = await CharacterCard.extractFromPng(file);
                if (!card) { alert('Invalid character card PNG.'); return; }
                dispatch({ type: 'IMPORT_WORLD', world: CharacterCard.toWorld(card) });
            } else {
                const reader = new FileReader();
                reader.onload = () => {
                    try {
                        const parsed = JSON.parse(reader.result as string);
                        if (CharacterCard.isCardData(parsed)) {
                            dispatch({ type: 'IMPORT_WORLD', world: CharacterCard.toWorld(parsed) });
                        } else if (isWorld(parsed)) {
                            dispatch({ type: 'IMPORT_WORLD', world: parsed });
                        } else if (isStory(parsed)) {
                            if (!currentWorld) { alert('Select a world first to import a story.'); return; }
                            dispatch({ type: 'IMPORT_STORY', worldId: currentWorld.id, story: parsed });
                        } else {
                            alert('Invalid file.');
                        }
                    } catch {
                        alert('Invalid file.');
                    }
                };
                reader.readAsText(file);
            }
        };
        input.click();
    };

    return (
        <div class={styles.menu}>
            <button class={styles.newButton} onClick={handleCreateWorld}>
                <Plus size={16} /> New World
            </button>
            <button class={styles.newButton} onClick={handleCreateChatWorld}>
                <MessagesSquare size={16} /> New Chat World
            </button>
            <button class={styles.newButton} onClick={handleImportWorld}>
                <Upload size={16} /> Import World
            </button>
            <div class={styles.list}>
                {worlds.map(world => (
                    <WorldItem
                        key={world.id}
                        world={world}
                        activeWorldId={currentWorld?.id ?? null}
                        activeStoryId={currentStory?.id ?? null}
                        onSelectWorld={() => handleSelectWorld(world.id)}
                        onRenameWorld={(title) => handleRenameWorld(world.id, title)}
                        onDeleteWorld={() => handleDeleteWorld(world.id)}
                        onExportWorld={() => handleExportWorld(world.id)}
                        onCreateStory={() => handleCreateStory(world.id)}
                        onSelectStory={(storyId) => handleSelectStory(world.id, storyId)}
                        onRenameStory={(storyId, title) => handleRenameStory(world.id, storyId, title)}
                        onDeleteStory={(storyId) => handleDeleteStory(world.id, storyId)}
                        onDuplicateStory={(storyId) => handleDuplicateStory(world.id, storyId)}
                        onExportStory={(storyId) => handleExportStory(world.id, storyId)}
                        onImportStory={() => handleImportStory(world.id)}
                    />
                ))}
            </div>
            <div class={styles.bottomButtons}>
                <button class={styles.settingsButton} onClick={isSettingsOpen.toggle}>
                    <Settings size={16} /> Settings
                </button>
            </div>

            <SettingsModal open={isSettingsOpen.value} onClose={isSettingsOpen.setFalse} />
        </div>
    );
};
