import { useState, useEffect, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import type { RecentApi, PopularApi, ServiceCatalog } from '../../types/apihub';
import { getRecentApis, getPopularApis, getCatalog } from '../../services/apiHubService';

const formatDomain = (d: string) => (/^[a-zA-Z\s\-_]+$/.test(d) ? d.toUpperCase() : d);

// 도메인 컬러 팔레트 (해시 기반 매핑)
const DOMAIN_COLOR_PALETTE = [
  { color: 'text-emerald-400', bg: 'bg-emerald-500/10', border: 'border-emerald-500/30', line: 'from-emerald-500' },
  { color: 'text-rose-400', bg: 'bg-rose-500/10', border: 'border-rose-500/30', line: 'from-rose-500' },
  { color: 'text-blue-400', bg: 'bg-blue-500/10', border: 'border-blue-500/30', line: 'from-blue-500' },
  { color: 'text-amber-400', bg: 'bg-amber-500/10', border: 'border-amber-500/30', line: 'from-amber-500' },
  { color: 'text-violet-400', bg: 'bg-violet-500/10', border: 'border-violet-500/30', line: 'from-violet-500' },
  { color: 'text-cyan-400', bg: 'bg-cyan-500/10', border: 'border-cyan-500/30', line: 'from-cyan-500' },
  { color: 'text-orange-400', bg: 'bg-orange-500/10', border: 'border-orange-500/30', line: 'from-orange-500' },
  { color: 'text-pink-400', bg: 'bg-pink-500/10', border: 'border-pink-500/30', line: 'from-pink-500' },
  { color: 'text-lime-400', bg: 'bg-lime-500/10', border: 'border-lime-500/30', line: 'from-lime-500' },
  { color: 'text-indigo-400', bg: 'bg-indigo-500/10', border: 'border-indigo-500/30', line: 'from-indigo-500' },
  { color: 'text-teal-400', bg: 'bg-teal-500/10', border: 'border-teal-500/30', line: 'from-teal-500' },
  { color: 'text-fuchsia-400', bg: 'bg-fuchsia-500/10', border: 'border-fuchsia-500/30', line: 'from-fuchsia-500' },
];

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;
  const pathRegex = /d="([^"]+)"/g;
  const matches: string[] = [];
  let m;
  while ((m = pathRegex.exec(iconPath)) !== null) {
    matches.push(m[1]);
  }
  return matches.length > 0 ? matches : [iconPath];
};

const domainColorCache = new Map<string, (typeof DOMAIN_COLOR_PALETTE)[0]>();
let nextColorIdx = 0;

const getDomainColorByHash = (domain: string) => {
  const key = domain.toUpperCase();
  const cached = domainColorCache.get(key);
  if (cached) return cached;
  const color = DOMAIN_COLOR_PALETTE[nextColorIdx % DOMAIN_COLOR_PALETTE.length];
  nextColorIdx++;
  domainColorCache.set(key, color);
  return color;
};

const RANK_BADGE_STYLES = [
  'bg-gradient-to-br from-yellow-400 to-amber-500',
  'bg-gradient-to-br from-gray-300 to-gray-400',
  'bg-gradient-to-br from-amber-600 to-amber-700',
];

const extractSettled = <T,>(result: PromiseSettledResult<{ data?: T }>, fallback: T): T => {
  if (result.status === 'fulfilled' && result.value.data !== undefined) {
    return result.value.data;
  }
  return fallback;
};

const truncate = (str: string, max: number): string =>
  str.length > max ? str.slice(0, max) + '...' : str;

const formatDate = (dateStr: string): string => {
  const d = new Date(dateStr);
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
};

interface FlatDomain {
  domain: string;
  iconPath: string | null;
  sortOrder: number;
  apiCount: number;
}

const ApiHubDashboardPage = () => {
  const navigate = useNavigate();
  const [catalog, setCatalog] = useState<ServiceCatalog[]>([]);
  const [recentApis, setRecentApis] = useState<RecentApi[]>([]);
  const [popularApis, setPopularApis] = useState<PopularApi[]>([]);
  const [isLoading, setIsLoading] = useState(true);

  const fetchAll = useCallback(async () => {
    try {
      const [catalogRes, recentRes, popularRes] = await Promise.allSettled([
        getCatalog(),
        getRecentApis(),
        getPopularApis(),
      ]);
      setCatalog(extractSettled<ServiceCatalog[]>(catalogRes, []));
      setRecentApis(extractSettled<RecentApi[]>(recentRes, []));
      setPopularApis(extractSettled<PopularApi[]>(popularRes, []));
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchAll();
  }, [fetchAll]);

  // 카탈로그에서 도메인 기준으로 플랫하게 집계
  const domainList = useMemo<FlatDomain[]>(() => {
    const map = new Map<string, { iconPath: string | null; sortOrder: number; apiCount: number }>();
    for (const svc of catalog) {
      for (const dg of svc.domains) {
        const key = dg.domain.toUpperCase();
        const existing = map.get(key);
        const apiCount = (existing?.apiCount ?? 0) + dg.apis.length;
        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, { iconPath, sortOrder, apiCount });
      }
    }
    return Array.from(map.entries())
      .map(([domain, { iconPath, sortOrder, apiCount }]) => ({ domain, iconPath, sortOrder, apiCount }))
      .sort((a, b) => a.sortOrder - b.sortOrder || a.domain.localeCompare(b.domain));
  }, [catalog]);

  const recentTop3 = recentApis.slice(0, 3);

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-64">
        <div className="text-gray-500 dark:text-gray-400">로딩 중...</div>
      </div>
    );
  }

  return (
    <div className="max-w-7xl mx-auto space-y-8">
      {/* 히어로 배너 */}
      <div className="relative overflow-hidden rounded-2xl bg-gradient-to-br from-indigo-950 via-indigo-800 to-indigo-600 p-8">
        {/* 장식 글로우 원 */}
        <div className="pointer-events-none absolute -right-16 -top-16 h-64 w-64 rounded-full bg-indigo-400 opacity-20 blur-3xl" />
        <div className="pointer-events-none absolute right-32 -top-8 h-32 w-32 rounded-full bg-purple-400 opacity-10 blur-2xl" />

        {/* 제목 */}
        <h1 className="mb-2 text-4xl font-extrabold tracking-tight text-white">S&amp;P API HUB</h1>
        <p className="text-indigo-200">S&amp;P 해양/선박 세계데이터를 직접 만나보세요.</p>
      </div>

      {/* 인기 API 섹션 */}
      {popularApis.length > 0 && (
        <div>
          <div className="mb-4 flex items-center gap-2">
            <div className="flex h-7 w-7 items-center justify-center rounded-lg bg-amber-500/20">
              <svg className="h-4 w-4 text-amber-400" viewBox="0 0 24 24" fill="currentColor">
                <path fillRule="evenodd" d="M12.963 2.286a.75.75 0 00-1.071-.136 9.742 9.742 0 00-3.539 6.176 7.547 7.547 0 01-1.705-1.715.75.75 0 00-1.152-.082A9 9 0 1015.68 4.534a7.46 7.46 0 01-2.717-2.248zM15.75 14.25a3.75 3.75 0 11-7.313-1.172c.628.465 1.35.81 2.133 1a5.99 5.99 0 011.925-3.546 3.75 3.75 0 013.255 3.718z" clipRule="evenodd" />
              </svg>
            </div>
            <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">인기 API</h2>
            <span className="ml-1 text-xs text-gray-400 dark:text-gray-500">최근 7일 기준</span>
          </div>
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            {popularApis.map((api, idx) => {
              const palette = api.domain ? getDomainColorByHash(api.domain) : DOMAIN_COLOR_PALETTE[4];
              return (
                <div
                  key={idx}
                  className="group flex flex-col rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-5 shadow-sm cursor-pointer transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md hover:border-indigo-400/50 dark:hover:border-indigo-500/50"
                  onClick={() =>
                    api.serviceId && api.apiId
                      ? navigate(`/api-hub/services/${api.serviceId}/apis/${api.apiId}`)
                      : undefined
                  }
                >
                  <div className="mb-3 flex items-center gap-2">
                    {/* 랭킹 뱃지 */}
                    <div
                      className={`flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg text-xs font-bold text-white shadow ${RANK_BADGE_STYLES[idx] ?? 'bg-gray-500'}`}
                    >
                      {idx + 1}
                    </div>
                    {api.domain && (
                      <span
                        className={`rounded-full px-2 py-0.5 text-xs font-medium truncate ${palette.bg} ${palette.color}`}
                      >
                        {formatDomain(api.domain)}
                      </span>
                    )}
                  </div>
                  <p
                    className="flex-1 text-sm font-semibold text-gray-900 dark:text-gray-100 truncate mb-4"
                    title={api.apiName}
                  >
                    {api.apiName}
                  </p>
                  <div className="flex items-end justify-between border-t border-gray-100 dark:border-gray-700 pt-3">
                    <div>
                      <p className="text-xs text-gray-400 dark:text-gray-500 mb-0.5">주간 호출</p>
                      <p className="text-xl font-bold text-gray-900 dark:text-gray-100">
                        {api.count.toLocaleString()}
                        <span className="ml-0.5 text-xs font-normal text-gray-400 dark:text-gray-500">회</span>
                      </p>
                    </div>
                    <svg className="h-7 w-10 text-indigo-400/60" fill="none" viewBox="0 0 40 28" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
                      <polyline points="2,22 8,16 14,20 22,8 28,14 36,4" />
                    </svg>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* 최신 등록 API 섹션 */}
      <div>
        <div className="mb-4 flex items-center gap-2">
          <div className="flex h-7 w-7 items-center justify-center rounded-lg bg-cyan-500/20">
            <svg className="h-4 w-4 text-cyan-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
              <path d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456z" />
            </svg>
          </div>
          <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">최신 등록 API</h2>
        </div>
        {recentTop3.length > 0 ? (
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            {recentTop3.map((api) => {
              const palette = api.apiDomain ? getDomainColorByHash(api.apiDomain) : DOMAIN_COLOR_PALETTE[4];
              return (
                <div
                  key={api.apiId}
                  className="group flex flex-col rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-5 shadow-sm cursor-pointer transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md hover:border-indigo-400/50 dark:hover:border-indigo-500/50"
                  onClick={() => navigate(`/api-hub/services/${api.serviceId}/apis/${api.apiId}`)}
                >
                  <div className="mb-2 flex items-center gap-2">
                    {api.apiDomain && (
                      <span
                        className={`rounded-full px-2 py-0.5 text-xs font-medium truncate ${palette.bg} ${palette.color}`}
                      >
                        {formatDomain(api.apiDomain)}
                      </span>
                    )}
                  </div>
                  <p
                    className="flex-1 text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1 truncate"
                    title={api.apiName}
                  >
                    {api.apiName}
                  </p>
                  {api.description && (
                    <p className="mb-3 text-xs text-gray-500 dark:text-gray-400 line-clamp-2">
                      {truncate(api.description, 80)}
                    </p>
                  )}
                  <div className="mt-auto flex items-center gap-1.5 text-xs text-gray-400 dark:text-gray-500">
                    <svg className="h-3.5 w-3.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
                      />
                    </svg>
                    {formatDate(api.createdAt)}
                  </div>
                </div>
              );
            })}
          </div>
        ) : (
          <div className="rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 p-8 text-center text-sm text-gray-400 dark:text-gray-500">
            등록된 API가 없습니다
          </div>
        )}
      </div>
      {/* 서비스 도메인 섹션 */}
      {domainList.length > 0 && (
        <div>
          <div className="mb-4 flex items-center gap-2">
            <div className="flex h-7 w-7 items-center justify-center rounded-lg bg-indigo-500/20">
              <svg className="h-4 w-4 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"
                />
              </svg>
            </div>
            <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">서비스 도메인</h2>
          </div>
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
            {domainList.map((item) => {
              const palette = getDomainColorByHash(item.domain);
              const iconPaths = parseIconPaths(item.iconPath);
              const imgSrc = `${import.meta.env.BASE_URL}images/domains/${item.domain.toLowerCase()}.jpg`;
              return (
                <div
                  key={item.domain}
                  onClick={() => navigate(`/api-hub/domains/${encodeURIComponent(item.domain)}`)}
                  className={`group relative overflow-hidden rounded-xl border bg-white dark:bg-gray-800 ${palette.border} cursor-pointer transition-all duration-200 hover:-translate-y-1 hover:shadow-xl`}
                >
                  <div className="relative h-[200px] overflow-hidden bg-gray-100 dark:bg-gray-700">
                    <img
                      src={imgSrc}
                      alt={item.domain}
                      className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
                      onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}
                    />
                    <div className="absolute inset-x-0 bottom-0 flex items-center justify-between bg-black/20 backdrop-blur-sm px-3.5 py-2.5">
                      <div className="flex items-center gap-2 min-w-0">
                        <div className={`flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg ${palette.bg}`}>
                          <svg
                            className={`h-4 w-4 ${palette.color}`}
                            fill="none"
                            viewBox="0 0 24 24"
                            stroke="currentColor"
                            strokeWidth={1.5}
                            strokeLinecap="round"
                            strokeLinejoin="round"
                          >
                            {iconPaths.map((d, i) => (
                              <path key={i} d={d} />
                            ))}
                          </svg>
                        </div>
                        <span className="text-sm font-semibold text-white truncate">
                          {formatDomain(item.domain)}
                        </span>
                      </div>
                      <span className="flex-shrink-0 text-xs font-semibold text-white/80">
                        {item.apiCount} APIs
                      </span>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
};

export default ApiHubDashboardPage;
