"use client";

import { useSearchStore } from "@/lib/search-store";
import { Fragment, useEffect, useMemo, useState } from "react";
import { useEditorStore } from "@/lib/store";
import { Command } from "cmdk";
import { Search, FileText, Folder } from "lucide-react";
import { filterPagesByQuery, parseSearchQuery } from "@/lib/search-query";

const RECENT_PAGE_IDS_KEY = "noteai-recent-page-ids";
const MAX_RECENT_PAGES = 30;

function escapeRegExp(input: string): string {
    return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function highlightText(text: string, terms: string[]) {
    if (!text || terms.length === 0) return text;
    const normalized = Array.from(new Set(terms.filter(Boolean).map((t) => t.toLowerCase())));
    if (normalized.length === 0) return text;

    const pattern = normalized.map(escapeRegExp).join("|");
    const regex = new RegExp(`(${pattern})`, "ig");
    const parts = text.split(regex);

    return parts.map((part, idx) => {
        const matched = normalized.includes(part.toLowerCase());
        return matched ? (
            <mark key={`${part}-${idx}`} className="rounded bg-yellow-200/70 px-0.5 text-foreground dark:bg-yellow-500/30">
                {part}
            </mark>
        ) : (
            <Fragment key={`${part}-${idx}`}>{part}</Fragment>
        );
    });
}

export function SearchCommand() {
    const { isOpen, setOpen, query, setQuery } = useSearchStore();
    const { pages, setActivePageId } = useEditorStore();
    const [recentPageIds, setRecentPageIds] = useState<string[]>(() => {
        if (typeof window === "undefined") return [];
        try {
            const raw = localStorage.getItem(RECENT_PAGE_IDS_KEY);
            if (!raw) return [];
            const parsed = JSON.parse(raw);
            return Array.isArray(parsed) ? parsed.filter((id): id is string => typeof id === "string") : [];
        } catch {
            return [];
        }
    });

    const parsedQuery = useMemo(() => parseSearchQuery(query), [query]);
    const filteredPages = useMemo(() => {
        const items = filterPagesByQuery(pages, query);
        const recentRank = new Map(recentPageIds.map((id, idx) => [id, idx]));

        return [...items].sort((a, b) => {
            const ra = recentRank.has(a.id) ? (recentRank.get(a.id) as number) : Number.MAX_SAFE_INTEGER;
            const rb = recentRank.has(b.id) ? (recentRank.get(b.id) as number) : Number.MAX_SAFE_INTEGER;
            if (ra !== rb) return ra - rb;
            const ta = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
            const tb = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
            return tb - ta;
        });
    }, [pages, query, recentPageIds]);

    useEffect(() => {
        const down = (e: KeyboardEvent) => {
            if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
                e.preventDefault();
                setOpen(!isOpen);
                return;
            }
            if (e.key === "Escape" && isOpen) {
                e.preventDefault();
                setOpen(false);
            }
        };

        document.addEventListener("keydown", down);
        return () => document.removeEventListener("keydown", down);
    }, [isOpen, setOpen]);

    const runCommand = (command: () => void) => {
        setOpen(false);
        command();
    };

    const rememberVisitedPage = (pageId: string) => {
        setRecentPageIds((prev) => {
            const next = [pageId, ...prev.filter((id) => id !== pageId)].slice(0, MAX_RECENT_PAGES);
            try {
                localStorage.setItem(RECENT_PAGE_IDS_KEY, JSON.stringify(next));
            } catch {
                // ignore storage failures
            }
            return next;
        });
    };

    if (!isOpen) return null;

    return (
        <div
            className="fixed inset-0 z-50 flex items-start justify-center bg-background/70 p-4 pt-[max(1rem,env(safe-area-inset-top))] backdrop-blur-sm animate-in fade-in duration-200 md:items-center"
            role="dialog"
            aria-modal="true"
            aria-label="搜索文档"
        >
            <div className="fixed inset-0" onClick={() => setOpen(false)} aria-hidden="true" />
            <div className="ui-card relative mt-10 w-full max-w-lg overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 md:mt-0">
                <Command className="w-full" shouldFilter={false}>
                    <div className="flex items-center border-b border-border/70 px-3">
                        <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" aria-hidden="true" />
                        <Command.Input
                            placeholder="搜索... 支持 tag:项目 type:file updated:7d"
                            value={query}
                            onValueChange={setQuery}
                            className="flex h-12 w-full bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground"
                            aria-label="搜索文档输入框"
                            autoFocus
                        />
                    </div>
                    <div className="border-b border-border/50 px-3 py-2 text-[11px] text-muted-foreground">
                        语法：`tag:标签` `type:file|folder` `updated:7d`
                    </div>
                    <Command.List className="max-h-[55vh] overflow-y-auto p-2 md:max-h-[320px]">
                        <Command.Empty className="py-8 text-center">
                            <div className="mx-auto flex h-10 w-10 items-center justify-center rounded-full border border-border/70 bg-muted/35 text-muted-foreground">
                                <Search size={16} />
                            </div>
                            <p className="mt-2 text-sm font-medium text-foreground">未找到匹配结果</p>
                            <p className="mt-1 text-xs text-muted-foreground">试试更短关键词，或使用 `tag:` `type:` `updated:` 组合筛选</p>
                        </Command.Empty>
                        <Command.Group heading="文档">
                            {filteredPages.map((page) => (
                                <Command.Item
                                    key={page.id}
                                    value={`${page.title} ${(page.tags || []).join(" ")}`}
                                    onSelect={() =>
                                        runCommand(() => {
                                            setActivePageId(page.id);
                                            rememberVisitedPage(page.id);
                                        })
                                    }
                                    className="flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-accent hover:text-accent-foreground aria-selected:bg-accent aria-selected:text-accent-foreground"
                                >
                                    {page.type === "folder" ? <Folder size={14} className="text-blue-500" /> : <FileText size={14} />}
                                    <span>{highlightText(page.title || "无标题", parsedQuery.textTerms)}</span>
                                    {page.tags && page.tags.length > 0 && (
                                        <span className="ml-auto truncate text-[10px] text-muted-foreground">{page.tags.slice(0, 2).join(" · ")}</span>
                                    )}
                                </Command.Item>
                            ))}
                        </Command.Group>
                    </Command.List>
                </Command>
            </div>
        </div>
    );
}
