"use client";

import { useSyncExternalStore } from "react";
import { cx } from "../core/utils";
import { COMPONENT_EXAMPLES } from "./component-registry";
import { ComponentEmpty, ComponentView } from "./component-view";
import { ThemeSwitch } from "./theme-switch";
import { TOKEN_MANIFEST } from "./token-manifest";
import { TokenView } from "./token-view";
import styles from "./dev-test.module.scss";

// 선택 상태는 URL 해시가 SSOT다 — 새로고침하거나 링크를 공유해도 보던 섹션이 유지되고,
// React state를 따로 두지 않으므로 둘이 어긋날 일이 없다.
// 형식: `#token:light` / `#component:button`
function subscribeHash(onChange: () => void): () => void {
  window.addEventListener("hashchange", onChange);
  return () => window.removeEventListener("hashchange", onChange);
}

function getHash(): string {
  return window.location.hash.slice(1);
}

function getServerHash(): string {
  return "";
}

function useSelection(): { kind: string; id: string } | null {
  const hash = useSyncExternalStore(subscribeHash, getHash, getServerHash);
  const [kind, id] = hash.split(":");
  return kind && id ? { kind, id } : null;
}

function select(kind: string, id: string): void {
  window.location.hash = `${kind}:${id}`;
}

/** 안내 항목의 식별자 — 등록된 컴포넌트 id와 겹치지 않게 별도로 둔다. */
const GUIDE_ID = "guide";

function isRegistered(id: string): boolean {
  return COMPONENT_EXAMPLES.some((example) => example.id === id);
}

/**
 * 사이드바 분류는 원본 JSON 파일 구조를 그대로 따른다 — Mode(Light/Dark),
 * Responsive(PC/Mobile), 그리고 단일 모드인 Size·Theme·Primitive. 이 화면의 목적이
 * Figma 변수 페이지와 1:1로 대조하는 것이라, 우리 CSS 그룹이 아니라 원본 구획이 기준이다.
 */
function groupedSections() {
  const groups: { category: string | null; sections: typeof TOKEN_MANIFEST }[] = [];

  for (const section of TOKEN_MANIFEST) {
    const last = groups[groups.length - 1];
    if (last && last.category === section.category && section.category !== null) {
      last.sections.push(section);
    } else {
      groups.push({ category: section.category, sections: [section] });
    }
  }

  return groups;
}

export function DevTestPage() {
  const selection = useSelection();
  const totalTokens = TOKEN_MANIFEST.reduce((sum, section) => sum + section.tokens.length, 0);
  const current = selection ?? { kind: "token", id: TOKEN_MANIFEST[0]?.id ?? "" };
  const activeSection = TOKEN_MANIFEST.find((section) => section.id === current.id);

  return (
    <div className={styles.shell}>
      <aside className={styles.sidebar}>
        <div className={styles.brand}>
          <span className={styles.brandTitle}>@fox 디자인 시스템</span>
          <span className={styles.brandNote}>개발 전용 테스트 페이지</span>
        </div>

        <ThemeSwitch />

        <nav className={styles.nav} aria-label="섹션">
          <div className={styles.navGroup}>
            <h2 className={styles.navGroupTitle}>토큰 · {totalTokens}</h2>

            {groupedSections().map((group) => (
              <div key={group.category ?? group.sections[0].id} className={styles.navSubGroup}>
                {group.category ? (
                  <h3 className={styles.navSubTitle}>{group.category}</h3>
                ) : null}
                <ul className={styles.navList}>
                  {group.sections.map((section) => (
                    <li key={section.id}>
                      <button
                        type="button"
                        className={styles.navItem}
                        aria-current={
                          current.kind === "token" && current.id === section.id ? "page" : undefined
                        }
                        onClick={() => select("token", section.id)}
                      >
                        <span>{section.label}</span>
                        <span className={styles.navCount}>{section.tokens.length}</span>
                      </button>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>

          <div className={styles.navGroup}>
            <h2 className={styles.navGroupTitle}>컴포넌트 · {COMPONENT_EXAMPLES.length}</h2>
            <ul className={styles.navList}>
              {COMPONENT_EXAMPLES.map((example) => (
                <li key={example.id}>
                  <button
                    type="button"
                    className={styles.navItem}
                    aria-current={
                      current.kind === "component" && current.id === example.id
                        ? "page"
                        : undefined
                    }
                    onClick={() => select("component", example.id)}
                  >
                    <span>{example.name}</span>
                    <span className={styles.navCount}>{example.variants.length}</span>
                  </button>
                </li>
              ))}

              {/* 컴포넌트가 아니라 안내 항목이라 항상 목록 맨 아래에 두고 생김새를 달리한다.
                  등록된 컴포넌트가 없을 때도 사라지지 않아야 추가 방법을 찾을 수 있다. */}
              <li>
                <button
                  type="button"
                  className={cx(styles.navItem, styles.navItemGuide)}
                  aria-current={
                    current.kind === "component" && !isRegistered(current.id) ? "page" : undefined
                  }
                  onClick={() => select("component", GUIDE_ID)}
                >
                  <span>추가 방법</span>
                  <span aria-hidden="true" className={styles.navGuideMark}>
                    +
                  </span>
                </button>
              </li>
            </ul>
          </div>
        </nav>
      </aside>

      <main className={styles.content}>
        {current.kind === "component" ? (
          (() => {
            const example = COMPONENT_EXAMPLES.find((entry) => entry.id === current.id);
            return example ? <ComponentView example={example} /> : <ComponentEmpty />;
          })()
        ) : activeSection ? (
          <TokenView section={activeSection} />
        ) : (
          <p className={styles.loading}>선택한 토큰 섹션이 없습니다.</p>
        )}
      </main>
    </div>
  );
}
