"use client";

import React, { Component } from "react";
import { cn } from "@/lib/utils";
import type { Editor, Range } from "@tiptap/core";

export type SlashItemGroup = "基础" | "列表" | "插入" | "样式";

export interface CommandItem {
    title: string;
    description?: string;
    group: SlashItemGroup;
    icon: React.ReactNode;
    shortcut?: string;
    command: (context: { editor: Editor; range: Range }) => void;
}

type CommandListProps = {
    items: CommandItem[];
    command: (item: CommandItem) => void;
};

type CommandListState = {
    selectedIndex: number;
};

export class CommandList extends Component<CommandListProps, CommandListState> {
    constructor(props: CommandListProps) {
        super(props);
        this.state = {
            selectedIndex: 0,
        };
    }

    componentDidUpdate(prevProps: CommandListProps) {
        if (this.props.items !== prevProps.items) {
            this.setState({ selectedIndex: 0 });
        }
    }

    onKeyDown({ event }: { event: KeyboardEvent }) {
        if (event.key === "ArrowUp") {
            this.upHandler();
            return true;
        }

        if (event.key === "ArrowDown") {
            this.downHandler();
            return true;
        }

        if (event.key === "Enter") {
            this.enterHandler();
            return true;
        }

        return false;
    }

    upHandler() {
        const total = this.getFlattenedItems().length;
        if (total === 0) return;
        this.setState((prev) => ({
            selectedIndex: (prev.selectedIndex + total - 1) % total,
        }));
    }

    downHandler() {
        const total = this.getFlattenedItems().length;
        if (total === 0) return;
        this.setState((prev) => ({
            selectedIndex: (prev.selectedIndex + 1) % total,
        }));
    }

    enterHandler() {
        this.selectItem(this.state.selectedIndex);
    }

    selectItem(index: number) {
        const items = this.getFlattenedItems();
        const item = items[index];

        if (item) {
            this.props.command(item);
        }
    }

    getFlattenedItems() {
        const grouped = this.groupItems(this.props.items);
        return Object.values(grouped).flat();
    }

    groupItems(items: CommandItem[]) {
        const groups: Record<SlashItemGroup, CommandItem[]> = {
            基础: [],
            列表: [],
            插入: [],
            样式: [],
        };

        items.forEach((item) => {
            groups[item.group].push(item);
        });

        return (Object.keys(groups) as SlashItemGroup[])
            .filter((key) => groups[key].length > 0)
            .reduce((obj, key) => {
                obj[key] = groups[key];
                return obj;
            }, {} as Record<SlashItemGroup, CommandItem[]>);
    }

    render() {
        const { items } = this.props;
        const { selectedIndex } = this.state;
        const grouped = this.groupItems(items);
        let globalIndex = 0;

        return (
            <div className="z-50 h-auto max-h-[65vh] w-[min(92vw,800px)] overflow-hidden rounded-xl border border-zinc-800 bg-zinc-950/95 shadow-2xl backdrop-blur-lg animate-in fade-in zoom-in-95 duration-200">
                <div className="columns-1 gap-2 p-2 space-y-3 sm:p-3 sm:space-y-4 md:columns-2 lg:columns-3">
                    {Object.entries(grouped).map(([groupName, groupItems]) => (
                        <div key={groupName} className="break-inside-avoid mb-4">
                            <div className="px-2 py-1.5 text-[10px] font-bold uppercase tracking-widest text-zinc-500 select-none mb-1">
                                {groupName}
                            </div>
                            <div className="space-y-0.5">
                                {groupItems.map((item, index) => {
                                    const currentGlobalIndex = globalIndex++;
                                    const isSelected = selectedIndex === currentGlobalIndex;
                                    return (
                                        <button
                                            className={cn(
                                                "flex items-center justify-between w-full rounded-md px-2 py-1.5 text-sm transition-all duration-200 select-none group",
                                                isSelected
                                                    ? "bg-zinc-800 text-zinc-100"
                                                    : "text-zinc-400 hover:bg-zinc-900/50 hover:text-zinc-200"
                                            )}
                                            key={`${item.title}-${index}`}
                                            onClick={() => this.selectItem(currentGlobalIndex)}
                                        >
                                            <div className="flex items-center gap-2">
                                                <div
                                                    className={cn(
                                                        "flex h-6 w-6 items-center justify-center rounded bg-zinc-900 shadow-sm border border-zinc-800",
                                                        isSelected ? "border-zinc-700 bg-zinc-700" : "group-hover:border-zinc-700"
                                                    )}
                                                >
                                                    {item.icon}
                                                </div>
                                                <span className="text-xs font-medium">{item.title}</span>
                                            </div>
                                            {item.shortcut && (
                                                <span className="text-[10px] font-mono text-zinc-600 group-hover:text-zinc-500 ml-4">
                                                    {item.shortcut}
                                                </span>
                                            )}
                                        </button>
                                    );
                                })}
                            </div>
                        </div>
                    ))}
                </div>
                {items.length === 0 && (
                    <div className="flex flex-col items-center justify-center py-6 text-zinc-500 w-full">
                        <p className="text-xs">没有匹配的命令</p>
                    </div>
                )}
            </div>
        );
    }
}
