import { useState, useEffect, useMemo } from 'react';
import { Outlet, NavLink, useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../hooks/useAuth';
import { useTheme } from '../hooks/useTheme';
import { getCatalog } from '../services/apiHubService';
import type { ServiceCatalog } from '../types/apihub';
import ApiRequestBasketProvider from '../store/ApiRequestBasketContext';
import { useApiRequestBasket } from '../hooks/useApiRequestBasket';
import ApiKeyRequestModal from '../components/ApiKeyRequestModal';

const ROLES = ['ADMIN', 'MANAGER', 'USER'] as const;

const DEFAULT_ICON_PATHS = ['M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 00-1.883 2.542l.857 6a2.25 2.25 0 002.227 1.932H19.05a2.25 2.25 0 002.227-1.932l.857-6a2.25 2.25 0 00-1.883-2.542m-16.5 0V6A2.25 2.25 0 016 3.75h3.879a1.5 1.5 0 011.06.44l2.122 2.12a1.5 1.5 0 001.06.44H18A2.25 2.25 0 0120.25 9v.776'];

/** iconPath 문자열에서 SVG path d 값 배열을 추출 */
const parseIconPaths = (iconPath: string | null): string[] => {
  if (!iconPath) return DEFAULT_ICON_PATHS;
  // <path d="..."/> 형태에서 d 값 추출
  const pathRegex = /d="([^"]+)"/g;
  const matches: string[] = [];
  let m;
  while ((m = pathRegex.exec(iconPath)) !== null) {
    matches.push(m[1]);
  }
  // d 태그가 없으면 단일 path d 값으로 간주
  return matches.length > 0 ? matches : [iconPath];
};

/** 도메인 인덱스를 기반으로 색상 팔레트 반환 */
const DOMAIN_COLORS = [
  { bg: 'bg-indigo-500', dot: 'bg-indigo-400', badge: 'bg-indigo-900/60 text-indigo-300' },
  { bg: 'bg-violet-500', dot: 'bg-violet-400', badge: 'bg-violet-900/60 text-violet-300' },
  { bg: 'bg-sky-500', dot: 'bg-sky-400', badge: 'bg-sky-900/60 text-sky-300' },
  { bg: 'bg-emerald-500', dot: 'bg-emerald-400', badge: 'bg-emerald-900/60 text-emerald-300' },
  { bg: 'bg-amber-500', dot: 'bg-amber-400', badge: 'bg-amber-900/60 text-amber-300' },
  { bg: 'bg-rose-500', dot: 'bg-rose-400', badge: 'bg-rose-900/60 text-rose-300' },
  { bg: 'bg-teal-500', dot: 'bg-teal-400', badge: 'bg-teal-900/60 text-teal-300' },
  { bg: 'bg-orange-500', dot: 'bg-orange-400', badge: 'bg-orange-900/60 text-orange-300' },
] as const;

const getDomainColor = (index: number) => DOMAIN_COLORS[index % DOMAIN_COLORS.length];

interface FlatDomainGroup {
  domain: string;
  iconPath: string | null;
  sortOrder: number;
  apis: { serviceId: number; apiId: number; apiName: string; apiPath: string; apiMethod: string }[];
}

const ApiHubLayoutInner = () => {
  const { user, setRole } = useAuth();
  const { theme, toggleTheme } = useTheme();
  const navigate = useNavigate();
  const location = useLocation();

  const [catalog, setCatalog] = useState<ServiceCatalog[]>([]);
  const [loading, setLoading] = useState(true);
  const [openDomains, setOpenDomains] = useState<Record<string, boolean>>({});
  const [searchQuery, setSearchQuery] = useState('');

  useEffect(() => {
    getCatalog()
      .then((res) => {
        const items = res.data ?? [];
        setCatalog(items);
      })
      .finally(() => setLoading(false));
  }, []);

  const toggleDomain = (key: string) => {
    setOpenDomains((prev) => ({ ...prev, [key]: !prev[key] }));
  };

  // 서비스 계층을 제거하고 도메인 기준으로 플랫하게 재그룹핑
  const domainGroups = useMemo<FlatDomainGroup[]>(() => {
    const map = new Map<string, { apis: FlatDomainGroup['apis']; iconPath: string | null; sortOrder: number }>();
    for (const svc of catalog) {
      for (const dg of svc.domains) {
        const key = dg.domain.toUpperCase();
        const existing = map.get(key);
        const apis = existing?.apis ?? [];
        apis.push(
          ...dg.apis.map((api) => ({
            serviceId: svc.serviceId,
            apiId: api.apiId,
            apiName: api.apiName,
            apiPath: api.apiPath,
            apiMethod: api.apiMethod,
          })),
        );
        // 첫 번째로 발견된 iconPath/sortOrder 사용
        const iconPath = existing?.iconPath !== undefined ? existing.iconPath : (dg.iconPath ?? null);
        const sortOrder = existing?.sortOrder !== undefined ? existing.sortOrder : (dg.sortOrder ?? Number.MAX_SAFE_INTEGER);
        map.set(key, { apis, iconPath, sortOrder });
      }
    }
    return Array.from(map.entries())
      .map(([domain, { apis, iconPath, sortOrder }]) => ({ domain, iconPath, sortOrder, apis }))
      .sort((a, b) => a.sortOrder - b.sortOrder || a.domain.localeCompare(b.domain));
  }, [catalog]);

  const filteredDomainGroups = useMemo(() => {
    if (!searchQuery.trim()) return domainGroups;
    const q = searchQuery.trim().toLowerCase();
    return domainGroups
      .map((dg) => {
        const domainMatch = dg.domain.toLowerCase().includes(q);
        const filteredApis = dg.apis.filter(
          (api) => api.apiName.toLowerCase().includes(q) || api.apiPath.toLowerCase().includes(q),
        );
        if (domainMatch) return dg;
        if (filteredApis.length > 0) return { ...dg, apis: filteredApis };
        return null;
      })
      .filter((dg): dg is NonNullable<typeof dg> => dg !== null);
  }, [domainGroups, searchQuery]);

  const isSearching = searchQuery.trim().length > 0;

  const totalApiCount = useMemo(() => domainGroups.reduce((sum, dg) => sum + dg.apis.length, 0), [domainGroups]);

  return (
    <div className="flex min-h-screen">
      {/* Sidebar */}
      <aside className="fixed left-0 top-0 h-screen w-[272px] bg-[var(--color-bg-surface)] flex flex-col border-r border-[var(--color-border)]">
        {/* 로고 영역 */}
        <div className="flex-shrink-0 border-b border-[var(--color-border)]">
          <button
            onClick={() => navigate('/api-hub')}
            className="flex items-center gap-3 px-5 h-14 w-full hover:bg-[var(--color-primary-subtle)] transition-colors"
          >
            {/* 브랜드 컬러 아이콘 배경 */}
            <div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-[var(--color-primary-600)] shadow-lg">
              <svg className="h-4.5 w-4.5 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
                <path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
              </svg>
            </div>
            <span className="text-sm font-bold tracking-widest text-[var(--color-text-primary)] uppercase">KCG API HUB</span>
          </button>
        </div>

        {/* 검색 영역 */}
        <div className="flex-shrink-0 px-4 pt-4 pb-2">
          <div className="relative">
            <svg
              className="absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-[var(--color-text-tertiary)] pointer-events-none"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
            </svg>
            <input
              type="text"
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              placeholder="API 검색..."
              className="w-full bg-[var(--color-bg-base)] border border-[var(--color-border)] text-[var(--color-text-primary)] placeholder-[var(--color-text-tertiary)] rounded-lg pl-8 pr-7 py-2 text-xs focus:ring-1 focus:ring-[var(--color-primary)] focus:border-[var(--color-primary)] focus:outline-none transition-colors"
            />
            {searchQuery && (
              <button
                onClick={() => setSearchQuery('')}
                className="absolute right-2 top-1/2 -translate-y-1/2 text-[var(--color-text-tertiary)] hover:text-[var(--color-text-secondary)] transition-colors"
              >
                <svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            )}
          </div>
          {/* API 수 요약 */}
          {!loading && (
            <p className="mt-2 text-[11px] text-[var(--color-text-tertiary)]">
              {filteredDomainGroups.length}개 도메인 · {filteredDomainGroups.reduce((s, dg) => s + dg.apis.length, 0)}개 API
            </p>
          )}
        </div>

        {/* 도메인 트리 */}
        <nav className="flex-1 overflow-y-auto px-2 py-1 space-y-0.5">
          {loading ? (
            <div className="flex items-center justify-center py-10">
              <svg className="h-5 w-5 animate-spin text-[var(--color-text-tertiary)]" fill="none" viewBox="0 0 24 24">
                <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
                <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
              </svg>
            </div>
          ) : filteredDomainGroups.length === 0 ? (
            <p className="text-xs text-[var(--color-text-tertiary)] text-center py-6">검색 결과가 없습니다</p>
          ) : (
            filteredDomainGroups.map((dg, domainIndex) => {
              const domainOpen = isSearching || (openDomains[dg.domain] ?? true);
              const color = getDomainColor(domainIndex);

              return (
                <div key={dg.domain} className="mb-0.5">
                  {/* 도메인 헤더 */}
                  <div className="flex w-full items-center rounded-lg hover:bg-[var(--color-primary-subtle)] transition-colors group">
                    {/* 도메인명 클릭 → 도메인 상세 페이지 이동 */}
                    <button
                      onClick={() => navigate(`/api-hub/domains/${encodeURIComponent(dg.domain)}`)}
                      className="flex flex-1 items-center gap-2.5 px-2 py-2 min-w-0"
                    >
                      {/* 도메인 색상 아이콘 배경 */}
                      <div className={`flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-md ${color.bg}`}>
                        <svg
                          className="h-3.5 w-3.5 text-white"
                          fill="none"
                          viewBox="0 0 24 24"
                          stroke="currentColor"
                          strokeWidth={1.8}
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        >
                          {parseIconPaths(dg.iconPath).map((d, i) => (
                            <path key={i} d={d} />
                          ))}
                        </svg>
                      </div>
                      <span className="flex-1 truncate text-xs font-semibold text-[var(--color-text-secondary)] group-hover:text-[var(--color-primary-text)] transition-colors tracking-wide">
                        {dg.domain}
                      </span>
                      {/* API 카운트 뱃지 */}
                      <span className={`flex-shrink-0 rounded-full px-1.5 py-0.5 text-[10px] font-medium ${color.badge}`}>
                        {dg.apis.length}
                      </span>
                    </button>
                    {/* 접힘/펼침 화살표 버튼 */}
                    <button
                      onClick={() => toggleDomain(dg.domain)}
                      className="flex-shrink-0 rounded-md p-1.5 mr-1 text-[var(--color-text-tertiary)] hover:text-[var(--color-text-secondary)] transition-colors"
                      title={domainOpen ? '접기' : '펼치기'}
                    >
                      <svg
                        className={`h-3 w-3 transition-transform ${domainOpen ? 'rotate-90' : ''}`}
                        fill="none"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                      >
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                      </svg>
                    </button>
                  </div>

                  {/* API 항목 목록 */}
                  {domainOpen && (
                    <div className="ml-3 mt-0.5 space-y-0.5 border-l border-[var(--color-border)] pl-3">
                      {dg.apis.map((api) => {
                        const apiPath = `/api-hub/services/${api.serviceId}/apis/${api.apiId}`;
                        const isActive = location.pathname === apiPath;

                        return (
                          <NavLink
                            key={`${api.serviceId}-${api.apiId}`}
                            to={apiPath}
                            className={`flex items-center gap-2 rounded-md px-2 py-1.5 text-xs truncate transition-colors ${
                              isActive
                                ? 'bg-[var(--color-primary)] text-white font-medium dark:bg-[var(--color-primary-subtle)] dark:text-[var(--color-primary-text)]'
                                : 'text-[var(--color-text-secondary)] hover:bg-[var(--color-primary-subtle)] hover:text-[var(--color-primary-text)]'
                            }`}
                          >
                            {/* 활성 시 좌측 도트 인디케이터 */}
                            <span className={`flex-shrink-0 h-1.5 w-1.5 rounded-full transition-colors ${
                              isActive ? `${color.dot}` : 'bg-[var(--color-border)]'
                            }`} />
                            <span className="truncate">{api.apiName}</span>
                          </NavLink>
                        );
                      })}
                    </div>
                  )}
                </div>
              );
            })
          )}
        </nav>

        {/* 하단 정보 */}
        {!loading && (
          <div className="flex-shrink-0 border-t border-[var(--color-border)] px-4 py-3">
            <div className="flex items-center justify-between text-[11px] text-[var(--color-text-tertiary)]">
              <span>전체 {totalApiCount}개 API</span>
              <span>{domainGroups.length}개 도메인</span>
            </div>
          </div>
        )}
      </aside>

      {/* Main content */}
      <div className="flex-1 ml-[272px]">
        {/* 헤더 */}
        <header className="h-14 bg-[var(--color-bg-surface)] border-b border-[var(--color-border)] flex items-center justify-between px-6">
          <div />
          <div className="flex items-center gap-3">
            {/* 테마 토글 */}
            <button
              onClick={toggleTheme}
              className="rounded-lg p-2 text-[var(--color-text-secondary)] hover:bg-[var(--color-bg-base)] hover:text-[var(--color-text-primary)] transition-colors"
              title={theme === 'light' ? 'Dark mode' : 'Light mode'}
            >
              {theme === 'light' ? (
                <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
                </svg>
              ) : (
                <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
                </svg>
              )}
            </button>
            {/* 역할 스위처 (알약 형태) */}
            <div className="flex rounded-full overflow-hidden border border-[var(--color-border)] bg-[var(--color-bg-base)] p-0.5">
              {ROLES.map((role) => (
                <button
                  key={role}
                  onClick={() => setRole(role)}
                  className={`rounded-full px-3 py-1 text-xs font-medium transition-colors ${
                    user?.role === role
                      ? 'bg-[var(--color-primary)] text-white shadow-sm dark:bg-[var(--color-primary-600)]'
                      : 'text-[var(--color-text-tertiary)] hover:text-[var(--color-text-secondary)]'
                  }`}
                >
                  {role}
                </button>
              ))}
            </div>
          </div>
        </header>

        {/* 콘텐츠 */}
        <main className="p-6 bg-[var(--color-bg-base)] min-h-[calc(100vh-3.5rem)]">
          <Outlet />
          <BasketFloatingPanel />
        </main>
      </div>
    </div>
  );
};

const BasketFloatingPanel = () => {
  const { items, removeItem, clearItems, isBasketOpen, setBasketOpen } = useApiRequestBasket();
  const [showModal, setShowModal] = useState(false);

  const handleOpenModal = () => {
    setBasketOpen(false);
    setShowModal(true);
  };

  if (items.length === 0 && !showModal) return null;

  return (
    <>
      {/* 플로팅 버튼/패널 */}
      {!showModal && (
        !isBasketOpen ? (
          <button
            onClick={() => setBasketOpen(true)}
            className="fixed right-6 bottom-6 z-40 flex items-center gap-2 rounded-xl bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] dark:bg-[var(--color-primary-600)] dark:hover:bg-[var(--color-primary-500)] text-white px-4 py-3 shadow-lg transition-colors"
          >
            <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
            </svg>
            <span className="text-sm font-semibold">신청함</span>
            <span className="flex h-5 w-5 items-center justify-center rounded-full bg-white text-[var(--color-primary-active)] text-xs font-bold">{items.length}</span>
          </button>
        ) : (
          <div className="fixed right-6 bottom-6 z-40 w-80 rounded-xl bg-[var(--color-bg-surface)] shadow-2xl border border-[var(--color-border)] flex flex-col max-h-96">
            <div className="flex items-center justify-between px-4 py-3 border-b border-[var(--color-border)] flex-shrink-0">
              <span className="text-sm font-bold text-[var(--color-text-primary)]">
                API 신청함
                <span className="ml-1.5 inline-flex items-center justify-center h-5 min-w-5 rounded-full bg-[var(--color-primary-subtle)] text-[var(--color-primary)] text-xs font-bold px-1">{items.length}건</span>
              </span>
              <button onClick={() => setBasketOpen(false)} className="text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors">
                <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /></svg>
              </button>
            </div>
            <div className="flex-1 overflow-y-auto">
              {(() => {
                const grouped = new Map<string, typeof items>();
                items.forEach((item) => {
                  const d = item.domain ? (/^[a-zA-Z\s\-_]+$/.test(item.domain) ? item.domain.toUpperCase() : item.domain) : '미분류';
                  const list = grouped.get(d) ?? [];
                  list.push(item);
                  grouped.set(d, list);
                });
                return Array.from(grouped.entries()).map(([domain, apis]) => (
                  <div key={domain}>
                    <div className="px-4 py-1.5 bg-[var(--color-bg-base)] border-b border-[var(--color-border)]">
                      <span className="text-xs font-semibold text-[var(--color-text-secondary)] uppercase tracking-wider">{domain}</span>
                    </div>
                    {apis.map((item) => (
                      <div key={item.apiId} className="flex items-center gap-2 px-4 py-2 border-b border-[var(--color-border)]">
                        <span className="flex-1 text-sm text-[var(--color-text-primary)] truncate">{item.apiName}</span>
                        <button onClick={() => removeItem(item.apiId)} className="flex-shrink-0 text-gray-400 hover:text-red-500 transition-colors">
                          <svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /></svg>
                        </button>
                      </div>
                    ))}
                  </div>
                ));
              })()}
            </div>
            <div className="flex gap-2 px-4 py-3 border-t border-[var(--color-border)] flex-shrink-0">
              <button onClick={clearItems} className="flex-1 rounded-lg border border-[var(--color-border-strong)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-bg-base)] text-xs font-medium py-2 transition-colors">전체 삭제</button>
              <button onClick={handleOpenModal} className="flex-1 rounded-lg bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] dark:bg-[var(--color-primary-600)] dark:hover:bg-[var(--color-primary-500)] text-white text-xs font-medium py-2 transition-colors">일괄 신청</button>
            </div>
          </div>
        )
      )}

      <ApiKeyRequestModal
        isOpen={showModal}
        onClose={() => setShowModal(false)}
        initialApiIds={items.map((i) => i.apiId)}
        initialApiNames={items.map((i) => i.apiName)}
        onSuccess={() => clearItems()}
      />
    </>
  );
};

const ApiHubLayoutWithProvider = () => (
  <ApiRequestBasketProvider>
    <ApiHubLayoutInner />
  </ApiRequestBasketProvider>
);

export default ApiHubLayoutWithProvider;
