import type { ReactElement } from "react";
import { useEffect, useId, useState } from "react";

export interface DebugRow {
  label: string;
  value: string;
  tone?: "ok" | "warn" | "blocked" | "source" | "pending" | "dev-live" | "error";
  copyable?: boolean;
}

export interface DebugSection {
  title: string;
  rows: DebugRow[];
  empty?: string;
}

interface DebugDialogProps {
  triggerLabel?: string;
  triggerTitle?: string;
  dialogId: string;
  title: string;
  sections: DebugSection[];
  rawJson?: unknown;
  empty?: string;
  className?: string;
}

function toneClass(tone: DebugRow["tone"]): string {
  if (tone === "ok" || tone === "warn" || tone === "blocked" || tone === "source" || tone === "pending" || tone === "dev-live" || tone === "error") return tone;
  return "source";
}

export function DebugDialog({ triggerLabel, triggerTitle, dialogId, title, sections, rawJson, empty, className }: DebugDialogProps): ReactElement {
  const fallbackId = useId();
  const id = dialogId || fallbackId;
  const triggerId = `${id}-trigger`;
  const [open, setOpen] = useState(false);

  useEffect(() => {
    if (!open) return;
    const handleKey = (event: KeyboardEvent) => {
      if (event.key === "Escape") setOpen(false);
    };
    window.addEventListener("keydown", handleKey);
    return () => window.removeEventListener("keydown", handleKey);
  }, [open]);

  const totalRows = sections.reduce((acc, section) => acc + section.rows.length, 0);
  const allEmpty = totalRows === 0 && !rawJson;

  return (
    <>
      <button
        type="button"
        className={`debug-dialog-trigger${className ? ` ${className}` : ""}`}
        id={triggerId}
        data-debug-dialog-trigger={id}
        aria-haspopup="dialog"
        aria-controls={id}
        title={triggerTitle ?? "打开调试信息弹窗"}
        onClick={() => setOpen(true)}
      >
        {triggerLabel ?? "调试信息"}
      </button>
      {open ? (
        <div
          className="debug-dialog-scrim"
          data-debug-dialog-scrim={id}
          role="presentation"
          onClick={(event) => {
            if (event.target === event.currentTarget) setOpen(false);
          }}
        >
          <dialog
            className="debug-dialog"
            id={id}
            data-debug-dialog={id}
            aria-labelledby={`${id}-title`}
            open
            onClick={(event) => event.stopPropagation()}
          >
            <header className="debug-dialog-head">
              <h3 id={`${id}-title`}>{title}</h3>
              <button type="button" className="debug-dialog-close" aria-label="关闭调试信息弹窗" onClick={() => setOpen(false)}>关闭</button>
            </header>
            <div className="debug-dialog-body">
              {allEmpty ? (
                <p className="debug-dialog-empty">{empty ?? "暂无可显示的调试信息。"}</p>
              ) : (
                <>
                  {sections.map((section) => {
                    if (section.rows.length === 0) {
                      return section.empty ? <p key={section.title} className="debug-dialog-section-empty">{section.empty}</p> : null;
                    }
                    return (
                      <section key={section.title} className="debug-dialog-section">
                        <h4>{section.title}</h4>
                        <div className="debug-dialog-rows" role="table" aria-label={section.title}>
                          {section.rows.map((row) => (
                            <div className="debug-dialog-row" role="row" key={row.label}>
                              <span className="debug-dialog-key" role="rowheader">{row.label}</span>
                              <span className={`debug-dialog-value mono tone-${toneClass(row.tone)}`} role="cell">{row.value}</span>
                            </div>
                          ))}
                        </div>
                      </section>
                    );
                  })}
                  {rawJson !== undefined && rawJson !== null ? (
                    <section className="debug-dialog-section">
                      <h4>原始 JSON</h4>
                      <pre className="debug-dialog-raw" data-debug-dialog-raw>{JSON.stringify(rawJson, null, 2)}</pre>
                    </section>
                  ) : null}
                </>
              )}
            </div>
          </dialog>
        </div>
      ) : null}
    </>
  );
}
