"use client";

import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { api, ApiError } from "../lib/api";
import type { Message } from "@slackwsh/contracts";
import { IconSearch } from "./icons";

interface ChannelOption {
  id: string | number;
  name: string | null;
}

interface Props {
  workspaceId: string;
  channels: ChannelOption[];
}

/**
 * Quick switcher / command palette (Feature 6.4) with Ctrl/Cmd+K as the
 * keyboard shortcut (12.7). Channel matches are instant (client-side
 * filter over the already-loaded channel list); message matches hit the
 * search endpoint (6.1) with a debounce since that's a real query.
 */
export function CommandPalette({ workspaceId, channels }: Props) {
  const router = useRouter();
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const [results, setResults] = useState<Array<{ message: Message; channelName: string | null; authorName: string }>>([]);
  const inputRef = useRef<HTMLInputElement>(null);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    function onKeyDown(e: KeyboardEvent) {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setOpen((prev) => !prev);
      } else if (e.key === "Escape") {
        setOpen(false);
      }
    }
    function onOpenRequest() {
      setOpen(true);
    }
    window.addEventListener("keydown", onKeyDown);
    window.addEventListener("slackwsh:open-palette", onOpenRequest);
    return () => {
      window.removeEventListener("keydown", onKeyDown);
      window.removeEventListener("slackwsh:open-palette", onOpenRequest);
    };
  }, []);

  useEffect(() => {
    if (open) {
      setQuery("");
      setResults([]);
      // Focus after the dialog paints — needed because it wasn't in the
      // DOM the instant this effect runs.
      requestAnimationFrame(() => inputRef.current?.focus());
    }
  }, [open]);

  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current);
    if (!query.trim() || query.startsWith("#")) {
      setResults([]);
      return;
    }
    debounceRef.current = setTimeout(() => {
      api
        .search(workspaceId, query)
        .then((res) => setResults(res.results))
        .catch((err) => {
          if (!(err instanceof ApiError)) setResults([]);
        });
    }, 250);
  }, [query, workspaceId]);

  if (!open) return null;

  const channelMatches = query.startsWith("#")
    ? channels.filter((c) => (c.name ?? "").toLowerCase().includes(query.slice(1).toLowerCase()))
    : query
      ? channels.filter((c) => (c.name ?? "").toLowerCase().includes(query.toLowerCase()))
      : channels;

  function goToChannel(channelId: string | number) {
    setOpen(false);
    router.push(`/channel?workspaceId=${workspaceId}&channelId=${channelId}`);
  }

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-label="Quick switcher"
      className="palette-backdrop"
      onClick={() => setOpen(false)}
    >
      <div className="palette" onClick={(e) => e.stopPropagation()}>
        <label className="palette-search">
          <IconSearch size={20} />
          <input
            ref={inputRef}
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Jump to a channel or search messages"
            aria-label="Search channels and messages"
          />
          <kbd>Esc</kbd>
        </label>
        <div className="palette-results">
          {channelMatches.length > 0 && (
            <div className="palette-section">
              <div className="palette-section-title">Channels</div>
              {channelMatches.slice(0, 6).map((c) => (
                <button type="button" key={String(c.id)} className="palette-item" onClick={() => goToChannel(c.id)}>
                  <span className="palette-item-icon">#</span>
                  <span>{c.name ?? c.id}</span>
                  <span className="sub">Channel</span>
                </button>
              ))}
            </div>
          )}
          {results.length > 0 && (
            <div className="palette-section">
              <div className="palette-section-title">Messages</div>
              {results.map((r) => (
                <button type="button" key={String(r.message.id)} className="palette-item palette-message-result" onClick={() => goToChannel(r.message.channelId)}>
                  <span className="palette-item-icon message" aria-hidden="true">⌕</span>
                  <span className="palette-message-copy">
                    <strong>{r.authorName} <small>in #{r.channelName ?? r.message.channelId}</small></strong>
                    <span>{r.message.text.slice(0, 100)}</span>
                  </span>
                </button>
              ))}
            </div>
          )}
          {query && channelMatches.length === 0 && results.length === 0 && (
            <div className="palette-empty">
              <IconSearch size={22} />
              <strong>No results found</strong>
              <span>Try another channel name or message keyword.</span>
            </div>
          )}
        </div>
        <div className="palette-hint">
          <span><kbd>Ctrl</kbd>/<kbd>⌘</kbd> + <kbd>K</kbd> to toggle</span>
          <span><kbd>Esc</kbd> to close</span>
        </div>
      </div>
    </div>
  );
}
