'use client';

import { useState, useMemo, useCallback } from 'react';
import {
  Search,
  Copy,
  Check,
  ChevronDown,
  ChevronRight,
  Layers,
  FileCode,
  Code,
  Eye,
  Loader2,
  X,
  List,
  GitFork,
} from 'lucide-react';
import { getComponentSource, type RegistryData, type ComponentEntry } from './actions';
import { UI_PREVIEWS } from './previews';
import ComponentRelationshipView from './ComponentRelationshipView';

interface ComponentRegistryClientProps {
  registry: RegistryData;
}

const TIER_CONFIG: Record<string, { label: string; color: string; bg: string; border: string }> = {
  ui: { label: 'UI', color: 'text-blue-700', bg: 'bg-blue-50', border: 'border-blue-200' },
  atoms: { label: 'Atoms', color: 'text-green-700', bg: 'bg-green-50', border: 'border-green-200' },
  molecules: { label: 'Molecules', color: 'text-purple-700', bg: 'bg-purple-50', border: 'border-purple-200' },
  organisms: { label: 'Organisms', color: 'text-orange-700', bg: 'bg-orange-50', border: 'border-orange-200' },
  common: { label: 'Common', color: 'text-teal-700', bg: 'bg-teal-50', border: 'border-teal-200' },
  layout: { label: 'Layout', color: 'text-indigo-700', bg: 'bg-indigo-50', border: 'border-indigo-200' },
  dev: { label: 'Dev', color: 'text-yellow-700', bg: 'bg-yellow-50', border: 'border-yellow-200' },
  domain: { label: 'Domain', color: 'text-gray-700', bg: 'bg-gray-50', border: 'border-gray-200' },
};

const ALL_TIERS = ['전체', 'ui', 'atoms', 'molecules', 'organisms', 'common', 'layout', 'dev', 'domain'];

function CopyButton({ text, label }: { text: string; label: string }) {
  const [copied, setCopied] = useState(false);

  const handleCopy = async (e: React.MouseEvent) => {
    e.stopPropagation();
    await navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <button
      onClick={handleCopy}
      className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors"
      title={label}
    >
      {copied ? <Check className="w-3.5 h-3.5 text-green-500" /> : <Copy className="w-3.5 h-3.5" />}
    </button>
  );
}

function TierBadge({ tier }: { tier: string }) {
  const config = TIER_CONFIG[tier] || TIER_CONFIG.domain;
  return (
    <span className={`text-xs px-1.5 py-0.5 rounded ${config.bg} ${config.color} ${config.border} border`}>
      {config.label}
    </span>
  );
}

function SourceCodeViewer({ source }: { source: string }) {
  const lines = source.split('\n');

  return (
    <div className="relative">
      <div className="absolute top-2 right-2 z-10">
        <CopyButton text={source} label="소스코드 전체 복사" />
      </div>
      <pre className="bg-gray-950 text-gray-300 rounded-lg p-4 text-xs overflow-x-auto max-h-[500px] overflow-y-auto leading-relaxed">
        <code>
          {lines.map((line, i) => (
            <div key={i} className="flex">
              <span className="text-gray-600 select-none w-10 text-right pr-3 shrink-0">
                {i + 1}
              </span>
              <span className="flex-1 whitespace-pre">{line}</span>
            </div>
          ))}
        </code>
      </pre>
    </div>
  );
}

function ComponentCard({
  comp,
  isExpanded,
  onToggle,
}: {
  comp: ComponentEntry;
  isExpanded: boolean;
  onToggle: () => void;
}) {
  const [activeTab, setActiveTab] = useState<'preview' | 'code'>('preview');
  const [source, setSource] = useState<string | null>(null);
  const [isLoadingSource, setIsLoadingSource] = useState(false);

  const importPath = '@/' + comp.filePath.replace(/^src\//, '').replace(/\.tsx$/, '');
  const hasPreview = !!UI_PREVIEWS[comp.fileName];

  const handleToggle = useCallback(async () => {
    if (!isExpanded) {
      // Opening: load source code
      if (!source && !isLoadingSource) {
        setIsLoadingSource(true);
        const result = await getComponentSource(comp.filePath);
        if (result.source) setSource(result.source);
        setIsLoadingSource(false);
      }
      if (hasPreview) {
        setActiveTab('preview');
      } else {
        setActiveTab('code');
      }
    }
    onToggle();
  }, [isExpanded, source, isLoadingSource, comp.filePath, hasPreview, onToggle]);

  const handleTabChange = useCallback(async (tab: 'preview' | 'code') => {
    setActiveTab(tab);
    if (tab === 'code' && !source && !isLoadingSource) {
      setIsLoadingSource(true);
      const result = await getComponentSource(comp.filePath);
      if (result.source) setSource(result.source);
      setIsLoadingSource(false);
    }
  }, [source, isLoadingSource, comp.filePath]);

  return (
    <div className={`bg-white dark:bg-gray-800 rounded-lg border transition-all ${
      isExpanded
        ? 'border-blue-400 dark:border-blue-500 shadow-md'
        : 'border-gray-200 dark:border-gray-700 hover:border-blue-400 dark:hover:border-blue-500 hover:shadow-sm'
    }`}>
      {/* Card Header */}
      <div
        role="button"
        tabIndex={0}
        onClick={handleToggle}
        onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleToggle(); } }}
        className="flex items-center justify-between p-3 w-full text-left cursor-pointer"
      >
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 flex-wrap">
            <span className="font-medium text-gray-900 dark:text-white">
              {comp.name}
            </span>
            {comp.isClientComponent && (
              <span className="text-xs px-1.5 py-0.5 rounded bg-amber-50 text-amber-700 border border-amber-200">
                client
              </span>
            )}
            {comp.hasProps && (
              <span className="text-xs px-1.5 py-0.5 rounded bg-sky-50 text-sky-700 border border-sky-200">
                {comp.propsName || 'Props'}
              </span>
            )}
            <span className="text-xs px-1.5 py-0.5 rounded bg-gray-100 dark:bg-gray-700 text-gray-500">
              {comp.exportType}
            </span>
            {hasPreview && (
              <span className="text-xs px-1.5 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-200">
                Preview
              </span>
            )}
          </div>
          <p className="text-xs text-gray-500 dark:text-gray-400 font-mono mt-1 truncate">
            {comp.filePath}
          </p>
        </div>
        <div className="flex items-center gap-2 ml-2 shrink-0">
          <span className="text-xs text-gray-400">{comp.lineCount}L</span>
          <CopyButton text={importPath} label={`복사: ${importPath}`} />
          {isExpanded ? (
            <ChevronDown className="w-4 h-4 text-gray-400" />
          ) : (
            <ChevronRight className="w-4 h-4 text-gray-400" />
          )}
        </div>
      </div>

      {/* Expanded Content */}
      {isExpanded && (
        <div className="border-t border-gray-200 dark:border-gray-700">
          {/* Tab Buttons */}
          <div className="flex items-center gap-1 px-3 pt-2">
            {hasPreview && (
              <button
                onClick={() => handleTabChange('preview')}
                className={`flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-t transition-colors ${
                  activeTab === 'preview'
                    ? 'bg-white dark:bg-gray-800 text-blue-600 border border-b-0 border-gray-200 dark:border-gray-700'
                    : 'text-gray-500 hover:text-gray-700'
                }`}
              >
                <Eye className="w-3.5 h-3.5" />
                미리보기
              </button>
            )}
            <button
              onClick={() => handleTabChange('code')}
              className={`flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-t transition-colors ${
                activeTab === 'code'
                  ? 'bg-white dark:bg-gray-800 text-blue-600 border border-b-0 border-gray-200 dark:border-gray-700'
                  : 'text-gray-500 hover:text-gray-700'
              }`}
            >
              <Code className="w-3.5 h-3.5" />
              소스코드
            </button>
          </div>

          {/* Tab Content */}
          <div className="p-3">
            {activeTab === 'preview' && hasPreview && (
              <div className="space-y-4">
                {UI_PREVIEWS[comp.fileName]!.map((preview) => (
                  <div key={preview.label}>
                    <p className="text-xs font-medium text-gray-500 mb-2">{preview.label}</p>
                    <div className="p-4 bg-white dark:bg-gray-900 rounded-lg border border-dashed border-gray-300 dark:border-gray-600">
                      {preview.render()}
                    </div>
                  </div>
                ))}
              </div>
            )}

            {activeTab === 'code' && (
              <>
                {isLoadingSource && (
                  <div className="flex items-center justify-center py-8">
                    <Loader2 className="w-5 h-5 animate-spin text-gray-400 mr-2" />
                    <span className="text-sm text-gray-500">소스코드 로딩 중...</span>
                  </div>
                )}
                {source && <SourceCodeViewer source={source} />}
                {!isLoadingSource && !source && (
                  <p className="text-sm text-gray-500 text-center py-4">소스코드를 불러올 수 없습니다.</p>
                )}
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

function CategorySection({
  category,
  components,
  tier,
  expandedCard,
  onCardToggle,
  defaultExpanded = true,
}: {
  category: string;
  components: ComponentEntry[];
  tier: string;
  expandedCard: string | null;
  onCardToggle: (filePath: string) => void;
  defaultExpanded?: boolean;
}) {
  const [expanded, setExpanded] = useState(defaultExpanded);

  // Group by subcategory
  const groups = useMemo(() => {
    const map = new Map<string, ComponentEntry[]>();
    for (const comp of components) {
      const key = comp.subcategory || '__root__';
      if (!map.has(key)) map.set(key, []);
      map.get(key)!.push(comp);
    }
    return map;
  }, [components]);

  return (
    <div className="mb-4">
      <button
        onClick={() => setExpanded(!expanded)}
        className="flex items-center gap-2 w-full text-left mb-2"
      >
        {expanded ? (
          <ChevronDown className="w-4 h-4 text-gray-500 shrink-0" />
        ) : (
          <ChevronRight className="w-4 h-4 text-gray-500 shrink-0" />
        )}
        <TierBadge tier={tier} />
        <h3 className="text-base font-semibold text-gray-900 dark:text-white">
          {category}
        </h3>
        <span className="text-sm text-gray-500 ml-auto">
          {components.length}
        </span>
      </button>

      {expanded && (
        <div className="pl-6 space-y-3">
          {[...groups.entries()]
            .sort(([a], [b]) => a.localeCompare(b))
            .map(([sub, comps]) => (
              <div key={sub}>
                {sub !== '__root__' && (
                  <p className="text-xs text-gray-500 dark:text-gray-400 font-medium mb-1.5 pl-1">
                    {sub}
                  </p>
                )}
                <div className="grid gap-1.5">
                  {comps.map((comp) => (
                    <ComponentCard
                      key={comp.filePath}
                      comp={comp}
                      isExpanded={expandedCard === comp.filePath}
                      onToggle={() => onCardToggle(comp.filePath)}
                    />
                  ))}
                </div>
              </div>
            ))}
        </div>
      )}
    </div>
  );
}

export default function ComponentRegistryClient({ registry }: ComponentRegistryClientProps) {
  const [viewMode, setViewMode] = useState<'list' | 'relationship'>('list');
  const [searchTerm, setSearchTerm] = useState('');
  const [activeTier, setActiveTier] = useState('전체');
  const [activeDomainCategory, setActiveDomainCategory] = useState('전체');
  const [expandedCard, setExpandedCard] = useState<string | null>(null);
  const [isAllExpanded, setIsAllExpanded] = useState(true);
  const [globalExpandKey, setGlobalExpandKey] = useState(0);

  const handleCardToggle = useCallback((filePath: string) => {
    setExpandedCard((prev) => (prev === filePath ? null : filePath));
  }, []);

  const handleTierChange = useCallback((tier: string) => {
    setActiveTier(tier);
    if (tier !== 'domain') setActiveDomainCategory('전체');
    setIsAllExpanded(tier !== 'domain');
    setGlobalExpandKey(prev => prev + 1);
  }, []);

  const handleDomainCategoryChange = useCallback((cat: string) => {
    setActiveDomainCategory(cat);
    if (cat !== '전체') {
      setIsAllExpanded(true);
      setGlobalExpandKey(prev => prev + 1);
    }
  }, []);

  const handleToggleAll = useCallback(() => {
    setIsAllExpanded(prev => !prev);
    setGlobalExpandKey(prev => prev + 1);
  }, []);

  const filtered = useMemo(() => {
    let comps = registry.components;

    if (activeTier !== '전체') {
      comps = comps.filter((c) => c.tier === activeTier);
    }

    if (activeTier === 'domain' && activeDomainCategory !== '전체') {
      comps = comps.filter((c) => c.category === activeDomainCategory);
    }

    if (searchTerm) {
      const q = searchTerm.toLowerCase();
      comps = comps.filter(
        (c) =>
          c.name.toLowerCase().includes(q) ||
          c.fileName.toLowerCase().includes(q) ||
          c.filePath.toLowerCase().includes(q) ||
          (c.propsName && c.propsName.toLowerCase().includes(q))
      );
    }

    return comps;
  }, [registry.components, activeTier, activeDomainCategory, searchTerm]);

  // Group filtered components by category
  const groupedByCategory = useMemo(() => {
    const map = new Map<string, { tier: string; components: ComponentEntry[] }>();
    for (const comp of filtered) {
      if (!map.has(comp.category)) {
        map.set(comp.category, { tier: comp.tier, components: [] });
      }
      map.get(comp.category)!.components.push(comp);
    }
    return [...map.entries()].sort(([, a], [, b]) => {
      const tierOrder = ALL_TIERS.indexOf(a.tier) - ALL_TIERS.indexOf(b.tier);
      if (tierOrder !== 0) return tierOrder;
      return a.tier.localeCompare(b.tier);
    });
  }, [filtered]);

  // Tier counts for chips
  const tierCounts = useMemo(() => {
    const counts: Record<string, number> = { '전체': registry.components.length };
    for (const comp of registry.components) {
      counts[comp.tier] = (counts[comp.tier] || 0) + 1;
    }
    return counts;
  }, [registry.components]);

  // Domain sub-categories for sub-filter chips
  const domainCategories = useMemo(() => {
    const cats = new Map<string, number>();
    for (const comp of registry.components) {
      if (comp.tier === 'domain') {
        cats.set(comp.category, (cats.get(comp.category) || 0) + 1);
      }
    }
    return [...cats.entries()]
      .sort(([, a], [, b]) => b - a)
      .map(([name, count]) => ({ name, count }));
  }, [registry.components]);

  // Count of previewable components (all tiers)
  const previewCount = useMemo(() => {
    return registry.components.filter(
      (c) => !!UI_PREVIEWS[c.fileName]
    ).length;
  }, [registry.components]);

  const generatedDate = new Date(registry.generatedAt).toLocaleString('ko-KR');

  return (
    <div className="min-h-screen bg-gray-50 dark:bg-gray-900 p-6">
      <div>
        {/* Header */}
        <div className="mb-6">
          <div className="flex items-center gap-2 mb-2">
            <Layers className="w-6 h-6 text-blue-500" />
            <h1 className="text-2xl font-bold text-gray-900 dark:text-white">
              Component Registry
            </h1>
            <span className="text-sm text-gray-500 ml-2">
              {registry.totalCount}개
            </span>
          </div>
          <div className="flex items-center gap-2 mt-1">
            <p className="text-xs text-gray-400 flex-1">
              스캔: {generatedDate} &middot; 새로고침으로 갱신 (실시간 스캔)
              &middot; 카드 클릭: 소스코드 보기 &middot; 프리뷰: {previewCount}개
            </p>
            <div className="flex items-center bg-gray-100 dark:bg-gray-800 rounded-lg p-0.5">
              <button
                onClick={() => setViewMode('list')}
                className={`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-colors ${
                  viewMode === 'list'
                    ? 'bg-white dark:bg-gray-700 text-blue-600 shadow-sm'
                    : 'text-gray-500 hover:text-gray-700'
                }`}
              >
                <List className="w-3.5 h-3.5" />
                목록
              </button>
              <button
                onClick={() => setViewMode('relationship')}
                className={`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-colors ${
                  viewMode === 'relationship'
                    ? 'bg-white dark:bg-gray-700 text-blue-600 shadow-sm'
                    : 'text-gray-500 hover:text-gray-700'
                }`}
              >
                <GitFork className="w-3.5 h-3.5" />
                관계도
              </button>
            </div>
          </div>
        </div>

        {/* Relationship View */}
        {viewMode === 'relationship' && (
          <ComponentRelationshipView components={registry.components} />
        )}

        {/* List View */}
        {viewMode === 'list' && (
          <>
            {/* Search */}
            <div className="relative mb-4">
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
              <input
                type="text"
                placeholder="컴포넌트명, 파일명, 경로 검색..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-full pl-10 pr-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
              />
              {searchTerm && (
                <button
                  onClick={() => setSearchTerm('')}
                  className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
                >
                  <X className="w-4 h-4" />
                </button>
              )}
            </div>

            {/* Tier Filter Chips */}
            <div className="flex flex-wrap gap-2 mb-6">
              {ALL_TIERS.map((tier) => {
                const isActive = activeTier === tier;
                const count = tierCounts[tier] || 0;
                if (tier !== '전체' && count === 0) return null;

                return (
                  <button
                    key={tier}
                    onClick={() => handleTierChange(tier)}
                    className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${
                      isActive
                        ? 'bg-blue-500 text-white'
                        : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 hover:border-blue-400'
                    }`}
                  >
                    {tier === '전체' ? '전체' : TIER_CONFIG[tier]?.label || tier}
                    <span className={`ml-1.5 text-xs ${isActive ? 'text-blue-100' : 'text-gray-400'}`}>
                      {count}
                    </span>
                  </button>
                );
              })}
            </div>

            {/* Domain Sub-filter Chips */}
            {activeTier === 'domain' && domainCategories.length > 0 && (
              <div className="flex flex-wrap gap-1.5 mb-4">
                <button
                  onClick={() => handleDomainCategoryChange('전체')}
                  className={`px-2.5 py-1 rounded-full text-xs font-medium transition-colors ${
                    activeDomainCategory === '전체'
                      ? 'bg-gray-700 text-white'
                      : 'bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-400 border border-gray-200 dark:border-gray-600 hover:border-gray-400'
                  }`}
                >
                  전체
                  <span className={`ml-1 ${activeDomainCategory === '전체' ? 'text-gray-300' : 'text-gray-400'}`}>
                    {tierCounts['domain'] || 0}
                  </span>
                </button>
                {domainCategories.map(({ name, count }) => (
                  <button
                    key={name}
                    onClick={() => handleDomainCategoryChange(name)}
                    className={`px-2.5 py-1 rounded-full text-xs font-medium transition-colors ${
                      activeDomainCategory === name
                        ? 'bg-gray-700 text-white'
                        : 'bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-400 border border-gray-200 dark:border-gray-600 hover:border-gray-400'
                    }`}
                  >
                    {name}
                    <span className={`ml-1 ${activeDomainCategory === name ? 'text-gray-300' : 'text-gray-400'}`}>
                      {count}
                    </span>
                  </button>
                ))}
              </div>
            )}

            {/* Results count & Expand/Collapse All */}
            <div className="flex items-center justify-between mb-4">
              {(searchTerm || activeTier !== '전체') ? (
                <p className="text-sm text-gray-500">
                  {filtered.length}개 결과
                </p>
              ) : <div />}
              {groupedByCategory.length > 1 && (
                <button
                  onClick={handleToggleAll}
                  className="text-xs text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
                >
                  {isAllExpanded ? '전체 접기' : '전체 펼치기'}
                </button>
              )}
            </div>

            {/* Component List */}
            <div className="space-y-2">
              {groupedByCategory.map(([category, { tier, components }]) => (
                <CategorySection
                  key={`${category}-${globalExpandKey}`}
                  category={category}
                  tier={tier}
                  components={components}
                  expandedCard={expandedCard}
                  onCardToggle={handleCardToggle}
                  defaultExpanded={isAllExpanded}
                />
              ))}
            </div>

            {/* Empty State */}
            {filtered.length === 0 && (
              <div className="text-center py-16">
                <FileCode className="w-12 h-12 text-gray-300 mx-auto mb-3" />
                <p className="text-gray-500">검색 결과가 없습니다.</p>
              </div>
            )}
          </>
        )}

        {/* Footer */}
        <div className="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-center text-sm text-gray-500">
          <p>
            실시간 스캔: <code className="bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded">src/components/**/*.tsx</code>
          </p>
        </div>
      </div>
    </div>
  );
}
