import {
  Component,
  createSignal,
  For,
  Show,
  onCleanup,
  onMount,
} from "solid-js";
import { docEntries, type DocEntry } from "./doc-data";
import { journalDocEntries, type JournalDocEntry } from "./journal-doc-data";

type DocSet = "directives" | "journal";
type AnyEntry = DocEntry | JournalDocEntry;

export interface DocDialogProps {
  isOpen: boolean;
  onClose: () => void;
}

const DocDialog: Component<DocDialogProps> = (props) => {
  const [docSet, setDocSet] = createSignal<DocSet>("directives");
  const [selectedTag, setSelectedTag] = createSignal(docEntries[0]?.tag ?? "");
  const [dropdownOpen, setDropdownOpen] = createSignal(false);
  let dropdownRef!: HTMLDivElement;

  const currentEntries = () =>
    docSet() === "directives"
      ? (docEntries as AnyEntry[])
      : (journalDocEntries as AnyEntry[]);

  const selectedEntry = () =>
    currentEntries().find((e) => e.tag === selectedTag()) ??
    currentEntries()[0];

  const docSetLabel = () =>
    docSet() === "directives" ? "指令组件文档" : "Journal 服务器文档";

  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.key === "Escape") props.onClose();
  };

  const switchDocSet = (set: DocSet) => {
    setDocSet(set);
    setDropdownOpen(false);
    const entries = set === "directives" ? docEntries : journalDocEntries;
    setSelectedTag(entries[0]?.tag ?? "");
  };

  onMount(() => {
    document.addEventListener("keydown", handleKeyDown);
    // Close dropdown on outside click
    document.addEventListener("click", (e) => {
      if (dropdownRef && !dropdownRef.contains(e.target as Node)) {
        setDropdownOpen(false);
      }
    });
  });

  onCleanup(() => {
    document.removeEventListener("keydown", handleKeyDown);
  });

  return (
    <Show when={props.isOpen}>
      <div
        class="fixed inset-0 bg-black/50 z-60 flex items-center justify-center p-4"
        onClick={(e) => {
          if (e.target === e.currentTarget) props.onClose();
        }}
      >
        <div class="bg-white rounded-lg shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col overflow-hidden">
          <div class="flex items-center justify-between px-6 py-4 border-b border-gray-200 shrink-0">
            <div ref={dropdownRef} class="relative">
              <button
                onClick={() => setDropdownOpen((v) => !v)}
                class="text-lg font-bold text-gray-900 hover:text-blue-600 flex items-center gap-1"
              >
                {docSetLabel()}
                <span class="text-gray-400 text-sm">▾</span>
              </button>
              <Show when={dropdownOpen()}>
                <div class="absolute top-full left-0 mt-1 w-52 bg-white border border-gray-200 rounded shadow-lg z-60 py-1">
                  <button
                    onClick={() => switchDocSet("directives")}
                    class={`w-full text-left px-3 py-2 text-sm hover:bg-gray-100 flex items-center gap-2 ${
                      docSet() === "directives"
                        ? "bg-blue-50 text-blue-700"
                        : "text-gray-700"
                    }`}
                  >
                    <span>📖</span>
                    <span>指令组件文档</span>
                    <Show when={docSet() === "directives"}>
                      <span class="ml-auto text-blue-500">✓</span>
                    </Show>
                  </button>
                  <button
                    onClick={() => switchDocSet("journal")}
                    class={`w-full text-left px-3 py-2 text-sm hover:bg-gray-100 flex items-center gap-2 ${
                      docSet() === "journal"
                        ? "bg-blue-50 text-blue-700"
                        : "text-gray-700"
                    }`}
                  >
                    <span>📋</span>
                    <span>Journal 服务器文档</span>
                    <Show when={docSet() === "journal"}>
                      <span class="ml-auto text-blue-500">✓</span>
                    </Show>
                  </button>
                </div>
              </Show>
            </div>
            <button
              onClick={props.onClose}
              class="text-gray-400 hover:text-gray-600 text-xl leading-none p-1"
              title="关闭"
            >
              ✕
            </button>
          </div>

          <div class="flex flex-1 min-h-0">
            <nav class="w-48 shrink-0 border-r border-gray-200 overflow-y-auto p-3 bg-gray-50">
              <For each={currentEntries()}>
                {(entry) => (
                  <button
                    onClick={() => setSelectedTag(entry.tag)}
                    class={`w-full text-left px-3 py-2 rounded mb-1 text-sm transition-colors ${
                      selectedTag() === entry.tag
                        ? "bg-blue-100 text-blue-800 font-medium"
                        : "text-gray-700 hover:bg-gray-100"
                    }`}
                  >
                    <span class="mr-2">{entry.icon}</span>
                    <Show
                      when={docSet() === "directives"}
                      fallback={<span class="text-xs">{entry.title}</span>}
                    >
                      <span class="font-mono text-xs">{`:${entry.tag}`}</span>
                    </Show>
                  </button>
                )}
              </For>
            </nav>

            <div class="flex-1 overflow-y-auto p-6">
              <Show when={selectedEntry()} keyed>
                {(entry) => <DocContent entry={entry} />}
              </Show>
            </div>
          </div>
        </div>
      </div>
    </Show>
  );
};

/** Single entry documentation content */
const DocContent: Component<{ entry: AnyEntry }> = (props) => {
  const e = props.entry;

  return (
    <div class="max-w-none">
      <h2 class="text-2xl font-bold text-gray-900 mb-2">
        {e.icon} {e.title}
        <code class="ml-3 text-base font-mono bg-gray-100 px-2 py-0.5 rounded text-blue-700">
          :{e.tag}
        </code>
      </h2>

      <p class="text-gray-600 mb-6">{e.description}</p>

      <div class="mb-6">
        <h3 class="text-sm font-semibold text-gray-500 uppercase mb-2">
          基本语法
        </h3>
        <pre class="bg-gray-900 text-gray-100 px-4 py-3 rounded-lg text-sm overflow-x-auto">
          <code>{e.syntax}</code>
        </pre>
      </div>

      <Show when={e.props.length > 0}>
        <div class="mb-6">
          <h3 class="text-sm font-semibold text-gray-500 uppercase mb-2">
            属性
          </h3>
          <table class="w-full text-sm border-collapse">
            <thead>
              <tr class="border-b border-gray-200">
                <th class="text-left py-2 pr-4 font-medium text-gray-600">
                  属性
                </th>
                <th class="text-left py-2 pr-4 font-medium text-gray-600">
                  类型
                </th>
                <th class="text-left py-2 pr-4 font-medium text-gray-600">
                  默认值
                </th>
                <th class="text-left py-2 font-medium text-gray-600">说明</th>
              </tr>
            </thead>
            <tbody>
              <For each={e.props}>
                {(prop) => (
                  <tr class="border-b border-gray-100">
                    <td class="py-2 pr-4">
                      <code class="bg-gray-100 px-1.5 py-0.5 rounded text-xs text-pink-700">
                        {prop.name}
                      </code>
                    </td>
                    <td class="py-2 pr-4">
                      <code class="text-xs text-gray-600">{prop.type}</code>
                    </td>
                    <td class="py-2 pr-4 text-xs text-gray-400">
                      {prop.default ?? "—"}
                    </td>
                    <td class="py-2 text-sm text-gray-600">{prop.desc}</td>
                  </tr>
                )}
              </For>
            </tbody>
          </table>
        </div>
      </Show>

      <div class="prose-sm max-w-none">
        <h3 class="text-sm font-semibold text-gray-500 uppercase mb-2">示例</h3>
        <div class="bg-gray-50 border border-gray-200 rounded-lg p-4 text-sm leading-relaxed whitespace-pre-wrap font-mono text-gray-800">
          {e.body}
        </div>
      </div>
    </div>
  );
};

export default DocDialog;
