@extends('layouts.app')

@section('title', '인터뷰 시나리오 관리')

@push('styles')
<style>
    .category-item { transition: background-color 0.15s; }
    .category-item:hover { background-color: #f3f4f6; }
    .category-item.active { background-color: #eff6ff; border-left: 3px solid #3b82f6; }
    .template-card { border: 1px solid #e5e7eb; border-radius: 8px; }
    .question-row { border-bottom: 1px solid #f3f4f6; }
    .question-row:last-child { border-bottom: none; }
    .question-row .q-delete-x { display: none; }
    .question-row:hover .q-delete-x { display: inline-flex; }
    .question-row .q-edit-btn { display: none; }
    .question-row:hover .q-edit-btn { display: flex; }
    .progress-bar-fill { transition: width 0.3s ease; }
    .modal-overlay { background: rgba(0,0,0,0.5); }
    .fade-in { animation: fadeIn 0.2s ease-in; }
    @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
    .tab-active { border-bottom: 2px solid #3b82f6; color: #3b82f6; font-weight: 600; }
    .tab-inactive { border-bottom: 2px solid transparent; color: #6b7280; }
    .tab-inactive:hover { color: #374151; border-bottom-color: #d1d5db; }
    .domain-item { transition: all 0.15s; cursor: pointer; }
    .domain-item:hover { background-color: #f3f4f6; }
    .domain-item.active { background-color: #eff6ff; border-left: 3px solid #3b82f6; }
    .project-card { transition: all 0.15s; cursor: pointer; border: 2px solid transparent; }
    .project-card:hover { border-color: #93c5fd; }
    .project-card.active { border-color: #3b82f6; background-color: #eff6ff; }
    .status-badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 9999px; font-size: 0.75rem; font-weight: 500; }
    .knowledge-card { border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; margin-bottom: 8px; }
    .confidence-bar { height: 4px; border-radius: 2px; background: #e5e7eb; }
    .confidence-fill { height: 100%; border-radius: 2px; transition: width 0.3s; }
</style>
@endpush

@section('content')
<div id="interview-scenario-root"></div>
@endsection

@push('scripts')
@include('partials.react-cdn')
<script src="https://unpkg.com/lucide@0.469.0?v={{ time() }}"></script>
@verbatim
<script type="text/babel">
const { useState, useEffect, useRef, useCallback } = React;

const CSRF_TOKEN = document.querySelector('meta[name="csrf-token"]')?.content;

// ============================================================
// API 헬퍼
// ============================================================
const api = {
    headers: () => ({
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': CSRF_TOKEN,
        'Accept': 'application/json',
    }),
    async get(url) {
        const res = await fetch(url, { headers: this.headers() });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json();
    },
    async post(url, data) {
        const res = await fetch(url, { method: 'POST', headers: this.headers(), body: JSON.stringify(data) });
        if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err.message || `HTTP ${res.status}`); }
        return res.json();
    },
    async put(url, data) {
        const res = await fetch(url, { method: 'PUT', headers: this.headers(), body: JSON.stringify(data) });
        if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err.message || `HTTP ${res.status}`); }
        return res.json();
    },
    async del(url) {
        const res = await fetch(url, { method: 'DELETE', headers: this.headers() });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json();
    },
};

// ============================================================
// Lucide 아이콘 헬퍼
// ============================================================
const createIcon = (name) => {
    const _def=((n)=>{const a={'check-circle':'CircleCheck','alert-circle':'CircleAlert','alert-triangle':'TriangleAlert','clipboard-check':'ClipboardCheck','arrow-up-circle':'CircleArrowUp','arrow-down-circle':'CircleArrowDown'};if(a[n]&&lucide[a[n]])return lucide[a[n]];const p=n.split('-').map(w=>w.charAt(0).toUpperCase()+w.slice(1)).join('');return lucide[p]||(lucide.icons&&lucide.icons[n])||null;})(name);
    const _c = s => s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
    return ({ className = "w-5 h-5", ...props }) => {
        if (!_def) return null;
        const [, attrs, children = []] = _def;
        const sp = { className };
        Object.entries(attrs).forEach(([k, v]) => { sp[_c(k)] = v; });
        Object.assign(sp, props);
        return React.createElement("svg", sp, ...children.map(([tag, ca], i) => {
            const cp = { key: i };
            if (ca) Object.entries(ca).forEach(([k, v]) => { cp[_c(k)] = v; });
            return React.createElement(tag, cp);
        }));
    };
};

const IconPlus = createIcon('plus');
const IconEdit = createIcon('pencil');
const IconTrash = createIcon('trash-2');
const IconCheck = createIcon('check');
const IconX = createIcon('x');
const IconClipboard = createIcon('clipboard-check');
const IconHistory = createIcon('history');
const IconPlay = createIcon('play');
const IconChevronRight = createIcon('chevron-right');
const IconLoader = createIcon('loader');
const IconCalendar = createIcon('calendar');
const IconUser = createIcon('user');
const IconBuilding = createIcon('building-2');
const IconFileText = createIcon('file-text');
const IconCheckCircle = createIcon('check-circle');
const IconUpload = createIcon('upload');
const IconFolder = createIcon('folder');
const IconFolderPlus = createIcon('folder-plus');
const IconBrain = createIcon('brain');
const IconCode = createIcon('code');
const IconPaperclip = createIcon('paperclip');
const IconMic = createIcon('mic');
const IconTarget = createIcon('target');
const IconSettings = createIcon('settings');
const IconDownload = createIcon('download');
const IconSearch = createIcon('search');
const IconRefresh = createIcon('refresh-cw');
const IconChevronDown = createIcon('chevron-down');
const IconShield = createIcon('shield-check');
const IconAlertCircle = createIcon('alert-circle');
const IconEye = createIcon('eye');
const IconHash = createIcon('hash');
const IconTable = createIcon('table');
const IconCalculator = createIcon('calculator');

// 트리에서 카테고리 검색 (루트 + children 2단계)
const findCategory = (tree, id) => {
    for (const cat of tree) {
        if (cat.id === id) return cat;
        if (cat.children) {
            const found = cat.children.find(c => c.id === id);
            if (found) return found;
        }
    }
    return null;
};

const DOMAIN_LABELS = {
    product_classification: '제품 분류 체계',
    bom_structure: 'BOM 구조',
    dimension_formula: '치수/변수 계산',
    component_config: '부품 구성 상세',
    pricing_structure: '단가 체계',
    quantity_formula: '수량 수식',
    conditional_logic: '조건부 로직',
    quote_format: '견적서 양식',
};

const DOMAIN_ICONS = {
    product_classification: 'folder',
    bom_structure: 'git-branch',
    dimension_formula: 'ruler',
    component_config: 'settings',
    pricing_structure: 'dollar-sign',
    quantity_formula: 'calculator',
    conditional_logic: 'git-merge',
    quote_format: 'file-text',
};

const STATUS_CONFIG = {
    draft: { label: '초안', bg: 'bg-gray-100', text: 'text-gray-700' },
    interviewing: { label: '인터뷰 진행중', bg: 'bg-blue-100', text: 'text-blue-700' },
    analyzing: { label: 'AI 분석중', bg: 'bg-yellow-100', text: 'text-yellow-700' },
    code_generated: { label: '코드 생성완료', bg: 'bg-green-100', text: 'text-green-700' },
    deployed: { label: '배포완료', bg: 'bg-purple-100', text: 'text-purple-700' },
};

const QUESTION_TYPE_LABELS = {
    checkbox: '체크박스',
    text: '텍스트',
    number: '숫자',
    select: '단일선택',
    multi_select: '다중선택',
    file_upload: '파일업로드',
    formula_input: '수식입력',
    table_input: '테이블입력',
    bom_tree: 'BOM 트리',
    price_table: '단가표',
    dimension_diagram: '치수다이어그램',
};

// ============================================================
// 루트 앱 — 프로젝트 모드 / 기존 모드 전환
// ============================================================
function InterviewScenarioApp() {
    const [mode, setMode] = useState('project'); // 'project' | 'legacy'
    const [tree, setTree] = useState([]);
    const [categories, setCategories] = useState([]);
    const [selectedCategoryId, setSelectedCategoryId] = useState(null);
    const [loading, setLoading] = useState(true);
    const [showSessionModal, setShowSessionModal] = useState(false);
    const [showHistoryModal, setShowHistoryModal] = useState(false);

    // 프로젝트 모드 상태
    const [projects, setProjects] = useState([]);
    const [selectedProjectId, setSelectedProjectId] = useState(null);
    const [projectTree, setProjectTree] = useState([]);
    const [selectedDomainCategoryId, setSelectedDomainCategoryId] = useState(null);
    const [activeTab, setActiveTab] = useState('questions'); // questions|interview|attachments|knowledge
    const [showProjectCreateModal, setShowProjectCreateModal] = useState(false);

    const loadTree = useCallback(async () => {
        try {
            const data = await api.get('/sales/interviews/api/tree');
            setTree(data);
            setCategories(data);
            if (!selectedCategoryId && data.length > 0) {
                // 첫 번째 루트의 첫 번째 자식 선택, 없으면 루트
                const first = data[0];
                const firstChild = first.children && first.children.length > 0 ? first.children[0] : first;
                setSelectedCategoryId(firstChild.id);
            }
        } catch (e) {
            console.error('트리 로드 실패:', e);
        } finally {
            setLoading(false);
        }
    }, [selectedCategoryId]);

    const loadProjects = useCallback(async () => {
        try {
            const data = await api.get('/sales/interviews/api/projects');
            setProjects(data.data || []);
        } catch (e) {
            console.error('프로젝트 로드 실패:', e);
        }
    }, []);

    const loadProjectTree = useCallback(async (projectId) => {
        if (!projectId) return;
        try {
            const data = await api.get(`/sales/interviews/api/projects/${projectId}/tree`);
            setProjectTree(data);
            if (data.length > 0 && !selectedDomainCategoryId) {
                const first = data[0];
                const firstChild = first.children && first.children.length > 0 ? first.children[0] : first;
                setSelectedDomainCategoryId(firstChild.id);
            }
        } catch (e) {
            console.error('프로젝트 트리 로드 실패:', e);
        }
    }, [selectedDomainCategoryId]);

    useEffect(() => { loadTree(); loadProjects(); }, []);

    useEffect(() => {
        if (selectedProjectId) {
            setSelectedDomainCategoryId(null);
            loadProjectTree(selectedProjectId);
        }
    }, [selectedProjectId]);

    const selectedCategory = findCategory(tree, selectedCategoryId);
    const selectedProject = projects.find(p => p.id === selectedProjectId);
    const selectedDomainCategory = findCategory(projectTree, selectedDomainCategoryId);

    if (loading) {
        return (
            <div className="flex items-center justify-center h-64">
                <IconLoader className="w-8 h-8 animate-spin text-blue-500" />
                <span className="ml-2 text-gray-500">로딩 중...</span>
            </div>
        );
    }

    return (
        <div className="space-y-4">
            {/* 헤더 */}
            <div className="flex items-center justify-between">
                <div className="flex items-center gap-2">
                    <IconClipboard className="w-6 h-6 text-blue-600" />
                    <h1 className="text-xl font-bold text-gray-900">인터뷰 시나리오 관리</h1>
                </div>
                <div className="flex gap-2">
                    <button onClick={() => setMode(mode === 'project' ? 'legacy' : 'project')}
                        className="flex items-center gap-1 px-3 py-2 text-sm bg-white border border-gray-300 rounded-lg hover:bg-gray-50">
                        {mode === 'project' ? <><IconSettings className="w-4 h-4" /> 기존 모드</> : <><IconFolder className="w-4 h-4" /> 프로젝트 모드</>}
                    </button>
                    <button onClick={() => setShowHistoryModal(true)}
                        className="flex items-center gap-1 px-3 py-2 text-sm bg-white border border-gray-300 rounded-lg hover:bg-gray-50">
                        <IconHistory className="w-4 h-4" /> 인터뷰 기록
                    </button>
                    <button onClick={() => mode === 'project' ? setShowProjectCreateModal(true) : setShowSessionModal(true)}
                        className="flex items-center gap-1 px-3 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700">
                        {mode === 'project' ? <><IconFolderPlus className="w-4 h-4" /> 새 프로젝트</> : <><IconPlay className="w-4 h-4" /> 인터뷰 실시</>}
                    </button>
                </div>
            </div>

            {mode === 'project' ? (
                <>
                    {/* 프로젝트 선택 바 */}
                    <ProjectSelector
                        projects={projects}
                        selectedId={selectedProjectId}
                        onSelect={(id) => { setSelectedProjectId(id); setActiveTab('questions'); }}
                        onRefresh={loadProjects}
                    />

                    {selectedProject ? (
                        <>
                            {/* 진행 상태 바 */}
                            <ProjectStatusBar project={selectedProject} onRefresh={() => { loadProjects(); loadProjectTree(selectedProjectId); }} />

                            {/* 탭 네비게이션 */}
                            <div className="flex border-b border-gray-200 bg-white rounded-t-lg">
                                {[
                                    { key: 'questions', label: '질문 편집', icon: IconEdit },
                                    { key: 'interview', label: '인터뷰', icon: IconPlay },
                                    { key: 'attachments', label: '첨부파일', icon: IconPaperclip },
                                    { key: 'knowledge', label: '추출 지식', icon: IconBrain },
                                ].map(tab => (
                                    <button key={tab.key} onClick={() => setActiveTab(tab.key)}
                                        className={`flex items-center gap-1.5 px-4 py-3 text-sm ${activeTab === tab.key ? 'tab-active' : 'tab-inactive'}`}>
                                        <tab.icon className="w-4 h-4" /> {tab.label}
                                    </button>
                                ))}
                            </div>

                            {/* 2-패널: 도메인 트리 + 콘텐츠 */}
                            <div className="flex gap-4" style={{ minHeight: '500px' }}>
                                {/* 좌측: 도메인 트리 */}
                                <div className="flex-shrink-0 bg-white border border-gray-200 rounded-lg overflow-hidden" style={{ width: '220px' }}>
                                    <DomainSidebar
                                        categories={projectTree}
                                        selectedId={selectedDomainCategoryId}
                                        onSelect={setSelectedDomainCategoryId}
                                    />
                                </div>

                                {/* 우측: 탭 콘텐츠 */}
                                <div className="flex-1 bg-white border border-gray-200 rounded-lg overflow-hidden">
                                    {activeTab === 'questions' && (
                                        <MainContent
                                            category={selectedDomainCategory}
                                            onRefresh={() => loadProjectTree(selectedProjectId)}
                                        />
                                    )}
                                    {activeTab === 'interview' && (
                                        <ProjectInterviewTab
                                            project={selectedProject}
                                            categories={projectTree}
                                            selectedCategoryId={selectedDomainCategoryId}
                                        />
                                    )}
                                    {activeTab === 'attachments' && (
                                        <ProjectAttachmentsTab
                                            projectId={selectedProjectId}
                                        />
                                    )}
                                    {activeTab === 'knowledge' && (
                                        <ProjectKnowledgeTab
                                            projectId={selectedProjectId}
                                        />
                                    )}
                                </div>
                            </div>
                        </>
                    ) : (
                        <div className="flex flex-col items-center justify-center h-64 bg-white border border-gray-200 rounded-lg">
                            <IconFolder className="w-12 h-12 text-gray-300 mb-3" />
                            <p className="text-gray-500 mb-4">프로젝트를 선택하거나 새 프로젝트를 생성하세요</p>
                            <button onClick={() => setShowProjectCreateModal(true)}
                                className="flex items-center gap-1 px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700">
                                <IconFolderPlus className="w-4 h-4" /> 새 프로젝트 생성
                            </button>
                        </div>
                    )}
                </>
            ) : (
                <>
                    {/* 기존 모드: 2-패널 레이아웃 */}
                    <div className="flex gap-4" style={{ minHeight: '600px' }}>
                        <div className="w-64 flex-shrink-0 bg-white border border-gray-200 rounded-lg overflow-hidden">
                            <CategorySidebar
                                categories={categories}
                                selectedId={selectedCategoryId}
                                onSelect={setSelectedCategoryId}
                                onRefresh={loadTree}
                            />
                        </div>
                        <div className="flex-1 bg-white border border-gray-200 rounded-lg overflow-hidden">
                            <MainContent
                                category={selectedCategory}
                                onRefresh={loadTree}
                            />
                        </div>
                    </div>
                </>
            )}

            {/* 모달 */}
            {showSessionModal && (
                <InterviewSessionModal
                    categories={categories}
                    onClose={() => setShowSessionModal(false)}
                    onComplete={() => { setShowSessionModal(false); loadTree(); }}
                />
            )}
            {showHistoryModal && (
                <SessionHistoryModal
                    categories={categories}
                    onClose={() => setShowHistoryModal(false)}
                />
            )}
            {showProjectCreateModal && (
                <ProjectCreateModal
                    onClose={() => setShowProjectCreateModal(false)}
                    onCreated={(project) => {
                        setShowProjectCreateModal(false);
                        loadProjects();
                        setSelectedProjectId(project.id);
                    }}
                />
            )}
        </div>
    );
}

// ============================================================
// 프로젝트 선택 바
// ============================================================
function ProjectSelector({ projects, selectedId, onSelect, onRefresh }) {
    return (
        <div className="flex items-center gap-2 overflow-x-auto pb-1">
            {projects.map(p => {
                const st = STATUS_CONFIG[p.status] || STATUS_CONFIG.draft;
                return (
                    <div key={p.id}
                        onClick={() => onSelect(p.id)}
                        className={`project-card flex-shrink-0 px-4 py-3 rounded-lg bg-white ${p.id === selectedId ? 'active' : ''}`}
                        style={{ minWidth: '180px' }}>
                        <div className="font-medium text-sm text-gray-900 truncate">{p.company_name}</div>
                        <div className="flex items-center gap-2 mt-1">
                            <span className={`status-badge ${st.bg} ${st.text}`}>{st.label}</span>
                            <span className="text-xs text-gray-400">{p.progress_percent}%</span>
                        </div>
                    </div>
                );
            })}
            {projects.length === 0 && (
                <div className="text-sm text-gray-400 py-2">프로젝트가 없습니다</div>
            )}
        </div>
    );
}

// ============================================================
// 프로젝트 상태 바
// ============================================================
function ProjectStatusBar({ project, onRefresh }) {
    const st = STATUS_CONFIG[project.status] || STATUS_CONFIG.draft;
    return (
        <div className="flex items-center gap-4 px-4 py-3 bg-white border border-gray-200 rounded-lg">
            <div className="flex items-center gap-2 flex-shrink-0">
                <IconTarget className="w-5 h-5 text-blue-500" />
                <span className="font-semibold text-gray-900">{project.company_name}</span>
                {project.company_type && <span className="text-sm text-gray-500">({project.company_type})</span>}
            </div>
            <div className="flex-1">
                <div className="flex items-center gap-2">
                    <div className="flex-1 h-2 bg-gray-200 rounded-full overflow-hidden">
                        <div className="h-full bg-blue-500 rounded-full progress-bar-fill" style={{ width: `${project.progress_percent}%` }}></div>
                    </div>
                    <span className="text-sm font-medium text-gray-600 flex-shrink-0">{project.progress_percent}%</span>
                </div>
            </div>
            <span className={`status-badge ${st.bg} ${st.text} flex-shrink-0`}>{st.label}</span>
            {project.contact_person && <span className="text-xs text-gray-400 flex-shrink-0">담당: {project.contact_person}</span>}
        </div>
    );
}

// ============================================================
// 도메인 사이드바
// ============================================================
function DomainSidebar({ categories, selectedId, onSelect }) {
    const [expandedRoots, setExpandedRoots] = useState(() => {
        const map = {};
        categories.forEach(c => { map[c.id] = true; });
        return map;
    });

    useEffect(() => {
        setExpandedRoots(prev => {
            const map = { ...prev };
            categories.forEach(c => { if (map[c.id] === undefined) map[c.id] = true; });
            return map;
        });
    }, [categories]);

    const toggleRoot = (id) => {
        setExpandedRoots(prev => ({ ...prev, [id]: !prev[id] }));
    };

    const countQuestions = (cat) => {
        let count = (cat.templates || []).reduce((sum, t) => sum + (t.questions || []).length, 0);
        (cat.children || []).forEach(child => {
            count += (child.templates || []).reduce((sum, t) => sum + (t.questions || []).length, 0);
        });
        return count;
    };

    return (
        <div className="h-full overflow-y-auto">
            <div className="px-3 py-3 border-b border-gray-200">
                <h3 className="text-sm font-semibold text-gray-700">도메인</h3>
            </div>
            <div className="py-1">
                {categories.map(root => {
                    const hasChildren = root.children && root.children.length > 0;
                    const expanded = expandedRoots[root.id];
                    return (
                        <div key={root.id}>
                            {/* 대분류 */}
                            <div className="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-50"
                                onClick={() => hasChildren ? toggleRoot(root.id) : onSelect(root.id)}>
                                <div className="flex items-center gap-1.5 min-w-0">
                                    {hasChildren && (
                                        <span className="text-xs text-gray-400" style={{ width: '14px', display: 'inline-block' }}>
                                            {expanded ? '▼' : '▶'}
                                        </span>
                                    )}
                                    <span className="text-xs">📁</span>
                                    <span className="text-sm font-medium text-gray-700 truncate">{root.name}</span>
                                </div>
                                <span className="text-xs text-gray-400 flex-shrink-0">{countQuestions(root)}</span>
                            </div>
                            {/* 중분류 (자식) */}
                            {hasChildren && expanded && root.children.map(child => {
                                const qCount = (child.templates || []).reduce((sum, t) => sum + (t.questions || []).length, 0);
                                return (
                                    <div key={child.id}
                                        onClick={() => onSelect(child.id)}
                                        className={`domain-item flex items-center justify-between py-2 pr-3 ${child.id === selectedId ? 'active' : ''}`}
                                        style={{ paddingLeft: '2rem' }}>
                                        <div className="flex items-center gap-2 min-w-0">
                                            <span className="text-xs">📋</span>
                                            <span className="text-sm truncate">{child.name}</span>
                                        </div>
                                        <span className="text-xs text-gray-400 flex-shrink-0">{qCount}</span>
                                    </div>
                                );
                            })}
                        </div>
                    );
                })}
            </div>
        </div>
    );
}

// ============================================================
// 프로젝트 생성 모달
// ============================================================
function ProjectCreateModal({ onClose, onCreated }) {
    const [companyName, setCompanyName] = useState('');
    const [companyType, setCompanyType] = useState('');
    const [contactPerson, setContactPerson] = useState('');
    const [contactInfo, setContactInfo] = useState('');
    const [saving, setSaving] = useState(false);

    const handleSubmit = async () => {
        if (!companyName.trim()) { alert('회사명을 입력하세요.'); return; }
        setSaving(true);
        try {
            const project = await api.post('/sales/interviews/api/projects', {
                company_name: companyName.trim(),
                company_type: companyType.trim() || null,
                contact_person: contactPerson.trim() || null,
                contact_info: contactInfo.trim() || null,
            });
            onCreated(project);
        } catch (e) {
            alert('프로젝트 생성 실패: ' + e.message);
        } finally {
            setSaving(false);
        }
    };

    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center modal-overlay fade-in" onClick={onClose}>
            <div className="bg-white rounded-xl shadow-xl" style={{ width: '480px' }} onClick={e => e.stopPropagation()}>
                <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200">
                    <h2 className="text-lg font-semibold text-gray-900">새 인터뷰 프로젝트</h2>
                    <button onClick={onClose} className="text-gray-400 hover:text-gray-600"><IconX className="w-5 h-5" /></button>
                </div>
                <div className="px-6 py-4 space-y-4">
                    <div>
                        <label className="block text-sm font-medium text-gray-700 mb-1">회사명 *</label>
                        <input type="text" value={companyName} onChange={e => setCompanyName(e.target.value)}
                            className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                            placeholder="예: ABC 방화셔터"
                            onKeyDown={e => e.key === 'Enter' && handleSubmit()} />
                    </div>
                    <div>
                        <label className="block text-sm font-medium text-gray-700 mb-1">업종</label>
                        <input type="text" value={companyType} onChange={e => setCompanyType(e.target.value)}
                            className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                            placeholder="예: 방화셔터, 블라인드, 금속가공" />
                    </div>
                    <div className="flex gap-3">
                        <div className="flex-1">
                            <label className="block text-sm font-medium text-gray-700 mb-1">담당자</label>
                            <input type="text" value={contactPerson} onChange={e => setContactPerson(e.target.value)}
                                className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                                placeholder="이름" />
                        </div>
                        <div className="flex-1">
                            <label className="block text-sm font-medium text-gray-700 mb-1">연락처</label>
                            <input type="text" value={contactInfo} onChange={e => setContactInfo(e.target.value)}
                                className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                                placeholder="전화/이메일" />
                        </div>
                    </div>
                    <div className="bg-blue-50 rounded-lg px-3 py-2 text-xs text-blue-700">
                        프로젝트 생성 시 8개 도메인의 마스터 질문이 자동으로 복제됩니다.
                    </div>
                </div>
                <div className="flex items-center justify-end gap-2 px-6 py-3 border-t border-gray-200 bg-gray-50 rounded-b-xl">
                    <button onClick={onClose} className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800">취소</button>
                    <button onClick={handleSubmit} disabled={saving}
                        className="px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50">
                        {saving ? '생성 중...' : '프로젝트 생성'}
                    </button>
                </div>
            </div>
        </div>
    );
}

// ============================================================
// 프로젝트 인터뷰 탭
// ============================================================
function ProjectInterviewTab({ project, categories, selectedCategoryId }) {
    const [sessionData, setSessionData] = useState(null);
    const [loadingSession, setLoadingSession] = useState(false);

    const startInterview = async () => {
        if (!selectedCategoryId) { alert('도메인을 선택하세요.'); return; }
        setLoadingSession(true);
        try {
            const session = await api.post('/sales/interviews/api/sessions', {
                interview_category_id: selectedCategoryId,
                interview_date: new Date().toISOString().split('T')[0],
                interviewee_company: project.company_name,
            });
            const detail = await api.get(`/sales/interviews/api/sessions/${session.id}`);
            setSessionData(detail);
        } catch (e) {
            alert('세션 시작 실패: ' + e.message);
        } finally {
            setLoadingSession(false);
        }
    };

    const handleSaveAnswer = async (sessionId, questionId, data) => {
        try {
            await api.post('/sales/interviews/api/sessions/save-answer', {
                session_id: sessionId,
                question_id: questionId,
                ...data,
            });
            const detail = await api.get(`/sales/interviews/api/sessions/${sessionId}`);
            setSessionData(detail);
        } catch (e) {
            console.error('답변 저장 실패:', e);
        }
    };

    if (!selectedCategoryId) {
        return (
            <div className="flex items-center justify-center h-64 text-gray-400">
                좌측에서 도메인을 선택하세요
            </div>
        );
    }

    if (!sessionData) {
        return (
            <div className="flex flex-col items-center justify-center h-64">
                <IconPlay className="w-10 h-10 text-gray-300 mb-3" />
                <p className="text-gray-500 mb-4">선택한 도메인의 인터뷰를 시작하세요</p>
                <button onClick={startInterview} disabled={loadingSession}
                    className="flex items-center gap-1 px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50">
                    {loadingSession ? <><IconLoader className="w-4 h-4 animate-spin" /> 준비 중...</> : <><IconPlay className="w-4 h-4" /> 인터뷰 시작</>}
                </button>
            </div>
        );
    }

    // 인터뷰 진행 뷰
    const grouped = {};
    (sessionData.answers || []).forEach(ans => {
        const tplId = ans.interview_template_id;
        if (!grouped[tplId]) grouped[tplId] = { template: ans.template, answers: [] };
        grouped[tplId].answers.push(ans);
    });

    return (
        <div className="overflow-y-auto p-4 space-y-4" style={{ maxHeight: '60vh' }}>
            {/* 진행률 */}
            <div className="flex items-center gap-3 mb-4">
                <div className="flex-1 h-2 bg-gray-200 rounded-full overflow-hidden">
                    <div className="h-full bg-green-500 rounded-full progress-bar-fill"
                        style={{ width: `${sessionData.total_questions > 0 ? Math.round(sessionData.answered_questions / sessionData.total_questions * 100) : 0}%` }} />
                </div>
                <span className="text-sm text-gray-600">{sessionData.answered_questions}/{sessionData.total_questions}</span>
            </div>

            {Object.entries(grouped).map(([tplId, { template, answers }]) => (
                <div key={tplId} className="border border-gray-200 rounded-lg overflow-hidden">
                    <div className="bg-gray-50 px-4 py-2 font-medium text-sm text-gray-700">
                        {template?.name || `항목 ${tplId}`}
                    </div>
                    <div className="divide-y divide-gray-100">
                        {answers.map(ans => (
                            <StructuredAnswerRow key={ans.id} answer={ans}
                                onSave={(data) => handleSaveAnswer(sessionData.id, ans.interview_question_id, data)} />
                        ))}
                    </div>
                </div>
            ))}

            {sessionData.status === 'in_progress' && (
                <div className="flex justify-end">
                    <button onClick={async () => {
                        await api.post(`/sales/interviews/api/sessions/${sessionData.id}/complete`);
                        setSessionData(null);
                    }}
                        className="px-4 py-2 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700">
                        인터뷰 완료
                    </button>
                </div>
            )}
        </div>
    );
}

// ============================================================
// 구조화 답변 행
// ============================================================
function StructuredAnswerRow({ answer, onSave }) {
    const q = answer.question;
    const qType = q?.question_type || 'checkbox';
    const typeLabel = QUESTION_TYPE_LABELS[qType] || qType;

    const handleCheckToggle = () => {
        onSave({ is_checked: !answer.is_checked });
    };

    const handleTextSave = (value) => {
        onSave({ is_checked: true, answer_text: value });
    };

    const handleDataSave = (data) => {
        onSave({ is_checked: true, answer_data: data });
    };

    return (
        <div className="px-4 py-3">
            <div className="flex items-start gap-3">
                <button onClick={handleCheckToggle}
                    className={`flex-shrink-0 w-5 h-5 rounded border mt-0.5 flex items-center justify-center ${answer.is_checked ? 'bg-blue-500 border-blue-500 text-white' : 'border-gray-300 hover:border-blue-400'}`}>
                    {answer.is_checked && <IconCheck className="w-3 h-3" />}
                </button>
                <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2">
                        <span className={`text-sm ${answer.is_checked ? 'text-gray-900' : 'text-gray-600'}`}>
                            {q?.question_text}
                        </span>
                        <span className="text-xs text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded">{typeLabel}</span>
                        {q?.is_required && <span className="text-xs text-red-500">*필수</span>}
                    </div>
                    {q?.ai_hint && <div className="text-xs text-blue-500 mt-0.5">{q.ai_hint}</div>}

                    {/* 타입별 입력 UI */}
                    <div className="mt-2">
                        {(qType === 'text' || qType === 'formula_input') && (
                            <AnswerTextInput value={answer.answer_text || ''} format={q?.expected_format}
                                onSave={handleTextSave} placeholder={qType === 'formula_input' ? '수식을 입력하세요 (예: W1 = W0 + 120)' : '답변을 입력하세요'} />
                        )}
                        {qType === 'number' && (
                            <AnswerTextInput value={answer.answer_text || ''} format={q?.expected_format}
                                onSave={handleTextSave} type="number" placeholder="숫자를 입력하세요" />
                        )}
                        {qType === 'select' && (
                            <AnswerSelectInput value={answer.answer_text || ''} options={q?.options?.choices || []}
                                onSave={handleTextSave} />
                        )}
                        {qType === 'multi_select' && (
                            <AnswerMultiSelectInput value={answer.answer_data || []} options={q?.options?.choices || []}
                                onSave={handleDataSave} />
                        )}
                        {qType === 'table_input' && (
                            <AnswerTableInput value={answer.answer_data || { rows: [] }} columns={q?.options?.columns || []}
                                onSave={handleDataSave} />
                        )}
                        {qType === 'file_upload' && (
                            <div className="text-xs text-gray-400">첨부파일 탭에서 파일을 업로드하세요</div>
                        )}
                        {(qType === 'bom_tree' || qType === 'price_table' || qType === 'dimension_diagram') && (
                            <AnswerTextInput value={answer.answer_text || ''} onSave={handleTextSave}
                                placeholder={`${typeLabel} 데이터를 텍스트로 입력하세요`} multiline />
                        )}
                    </div>
                </div>
            </div>
        </div>
    );
}

// ============================================================
// 답변 입력 컴포넌트들
// ============================================================
function AnswerTextInput({ value, onSave, placeholder = '', format, type = 'text', multiline = false }) {
    const [text, setText] = useState(value);
    const [editing, setEditing] = useState(false);

    if (!editing && text) {
        return (
            <div className="flex items-center gap-2 cursor-pointer group" onClick={() => setEditing(true)}>
                <span className="text-sm text-gray-700">{text}</span>
                {format && <span className="text-xs text-gray-400">{format}</span>}
                <IconEdit className="w-3 h-3 text-gray-300 group-hover:text-gray-500" />
            </div>
        );
    }

    const InputTag = multiline ? 'textarea' : 'input';
    return (
        <div className="flex items-center gap-2">
            <InputTag type={type} value={text} onChange={e => setText(e.target.value)}
                className="flex-1 px-2 py-1 border border-gray-300 rounded text-sm focus:ring-1 focus:ring-blue-500"
                placeholder={placeholder}
                rows={multiline ? 3 : undefined}
                onKeyDown={e => { if (e.key === 'Enter' && !multiline) { onSave(text); setEditing(false); } }}
                autoFocus />
            {format && <span className="text-xs text-gray-400 flex-shrink-0">{format}</span>}
            <button onClick={() => { onSave(text); setEditing(false); }}
                className="px-2 py-1 text-xs bg-blue-500 text-white rounded hover:bg-blue-600">저장</button>
        </div>
    );
}

function AnswerSelectInput({ value, options, onSave }) {
    return (
        <select value={value} onChange={e => onSave(e.target.value)}
            className="px-2 py-1 border border-gray-300 rounded text-sm focus:ring-1 focus:ring-blue-500">
            <option value="">선택하세요</option>
            {options.map(opt => <option key={opt} value={opt}>{opt}</option>)}
        </select>
    );
}

function AnswerMultiSelectInput({ value, options, onSave }) {
    const selected = Array.isArray(value) ? value : [];
    const toggle = (opt) => {
        const next = selected.includes(opt) ? selected.filter(v => v !== opt) : [...selected, opt];
        onSave(next);
    };
    return (
        <div className="flex flex-wrap gap-1.5">
            {options.map(opt => (
                <button key={opt} onClick={() => toggle(opt)}
                    className={`px-2 py-1 text-xs rounded-full border ${selected.includes(opt) ? 'bg-blue-100 border-blue-300 text-blue-700' : 'bg-white border-gray-200 text-gray-600 hover:border-blue-200'}`}>
                    {opt}
                </button>
            ))}
        </div>
    );
}

function AnswerTableInput({ value, columns, onSave }) {
    const rows = value?.rows || [];
    const [localRows, setLocalRows] = useState(rows);

    const addRow = () => {
        const newRow = {};
        columns.forEach(c => { newRow[c] = ''; });
        const updated = [...localRows, newRow];
        setLocalRows(updated);
        onSave({ rows: updated });
    };

    const updateCell = (rowIdx, col, val) => {
        const updated = [...localRows];
        updated[rowIdx] = { ...updated[rowIdx], [col]: val };
        setLocalRows(updated);
    };

    const saveAll = () => {
        onSave({ rows: localRows });
    };

    const removeRow = (idx) => {
        const updated = localRows.filter((_, i) => i !== idx);
        setLocalRows(updated);
        onSave({ rows: updated });
    };

    return (
        <div className="space-y-1">
            <div className="overflow-x-auto">
                <table className="text-xs w-full border-collapse">
                    <thead>
                        <tr className="bg-gray-50">
                            {columns.map(col => (
                                <th key={col} className="px-2 py-1 text-left border border-gray-200 font-medium text-gray-600">{col}</th>
                            ))}
                            <th className="px-2 py-1 border border-gray-200 w-8"></th>
                        </tr>
                    </thead>
                    <tbody>
                        {localRows.map((row, ri) => (
                            <tr key={ri}>
                                {columns.map(col => (
                                    <td key={col} className="border border-gray-200 p-0">
                                        <input type="text" value={row[col] || ''} onChange={e => updateCell(ri, col, e.target.value)}
                                            onBlur={saveAll}
                                            className="w-full px-2 py-1 text-xs border-0 focus:ring-0" />
                                    </td>
                                ))}
                                <td className="border border-gray-200 text-center">
                                    <button onClick={() => removeRow(ri)} className="text-red-400 hover:text-red-600">
                                        <IconX className="w-3 h-3" />
                                    </button>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </table>
            </div>
            <button onClick={addRow} className="text-xs text-blue-500 hover:text-blue-700">+ 행 추가</button>
        </div>
    );
}

// ============================================================
// 첨부파일 탭
// ============================================================
function ProjectAttachmentsTab({ projectId }) {
    const [attachments, setAttachments] = useState([]);
    const [loading, setLoading] = useState(true);
    const [uploading, setUploading] = useState(false);
    const fileInput = useRef(null);
    const [fileType, setFileType] = useState('other');

    const load = useCallback(async () => {
        try {
            const data = await api.get(`/sales/interviews/api/projects/${projectId}/attachments`);
            setAttachments(data);
        } catch (e) { console.error(e); }
        finally { setLoading(false); }
    }, [projectId]);

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

    const handleUpload = async (e) => {
        const file = e.target.files[0];
        if (!file) return;
        setUploading(true);
        try {
            const form = new FormData();
            form.append('file', file);
            form.append('file_type', fileType);
            const res = await fetch(`/sales/interviews/api/projects/${projectId}/attachments`, {
                method: 'POST',
                headers: { 'X-CSRF-TOKEN': CSRF_TOKEN, 'Accept': 'application/json' },
                body: form,
            });
            if (!res.ok) throw new Error(`HTTP ${res.status}`);
            load();
        } catch (e) { alert('업로드 실패: ' + e.message); }
        finally { setUploading(false); if (fileInput.current) fileInput.current.value = ''; }
    };

    const handleDelete = async (id) => {
        if (!confirm('삭제하시겠습니까?')) return;
        try {
            await api.del(`/sales/interviews/api/attachments/${id}`);
            load();
        } catch (e) { alert('삭제 실패: ' + e.message); }
    };

    const FILE_TYPE_LABELS = {
        excel_template: '엑셀 템플릿',
        pdf_quote: 'PDF 견적서',
        sample_bom: 'BOM 샘플',
        price_list: '단가표',
        photo: '사진',
        voice: '음성녹음',
        other: '기타',
    };

    return (
        <div className="p-4 space-y-4">
            <div className="flex items-center gap-3">
                <select value={fileType} onChange={e => setFileType(e.target.value)}
                    className="px-2 py-1.5 border border-gray-300 rounded text-sm">
                    {Object.entries(FILE_TYPE_LABELS).map(([k, v]) => (
                        <option key={k} value={k}>{v}</option>
                    ))}
                </select>
                <button onClick={() => fileInput.current?.click()} disabled={uploading}
                    className="flex items-center gap-1 px-3 py-1.5 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50">
                    <IconUpload className="w-4 h-4" /> {uploading ? '업로드 중...' : '파일 업로드'}
                </button>
                <input ref={fileInput} type="file" className="hidden" onChange={handleUpload} accept="*/*" />
            </div>

            {loading ? (
                <div className="flex items-center justify-center h-32">
                    <IconLoader className="w-6 h-6 animate-spin text-blue-500" />
                </div>
            ) : attachments.length === 0 ? (
                <div className="flex flex-col items-center justify-center h-32 text-gray-400">
                    <IconPaperclip className="w-8 h-8 mb-2" />
                    <span>첨부파일이 없습니다</span>
                </div>
            ) : (
                <div className="space-y-2">
                    {attachments.map(att => (
                        <div key={att.id} className="flex items-center justify-between px-4 py-3 border border-gray-200 rounded-lg">
                            <div className="flex items-center gap-3">
                                <IconFileText className="w-5 h-5 text-gray-400" />
                                <div>
                                    <div className="text-sm font-medium text-gray-900">{att.file_name}</div>
                                    <div className="flex items-center gap-2 text-xs text-gray-400">
                                        <span>{FILE_TYPE_LABELS[att.file_type] || att.file_type}</span>
                                        <span>{(att.file_size / 1024).toFixed(1)}KB</span>
                                        <span className={`status-badge ${att.ai_analysis_status === 'completed' ? 'bg-green-100 text-green-700' : att.ai_analysis_status === 'processing' ? 'bg-yellow-100 text-yellow-700' : 'bg-gray-100 text-gray-600'}`}>
                                            AI: {att.ai_analysis_status}
                                        </span>
                                    </div>
                                </div>
                            </div>
                            <button onClick={() => handleDelete(att.id)} className="text-red-400 hover:text-red-600">
                                <IconTrash className="w-4 h-4" />
                            </button>
                        </div>
                    ))}
                </div>
            )}
        </div>
    );
}

// ============================================================
// 지식 탭
// ============================================================
function ProjectKnowledgeTab({ projectId }) {
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);
    const [domainFilter, setDomainFilter] = useState('');
    const [verifiedFilter, setVerifiedFilter] = useState('');
    const [showAddForm, setShowAddForm] = useState(false);

    const load = useCallback(async () => {
        try {
            let url = `/sales/interviews/api/projects/${projectId}/knowledge?`;
            if (domainFilter) url += `domain=${domainFilter}&`;
            if (verifiedFilter) url += `is_verified=${verifiedFilter}&`;
            const data = await api.get(url);
            setItems(data);
        } catch (e) { console.error(e); }
        finally { setLoading(false); }
    }, [projectId, domainFilter, verifiedFilter]);

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

    const handleVerify = async (id) => {
        try {
            await api.post(`/sales/interviews/api/knowledge/${id}/verify`);
            load();
        } catch (e) { alert('검증 토글 실패: ' + e.message); }
    };

    const handleDelete = async (id) => {
        if (!confirm('삭제하시겠습니까?')) return;
        try {
            await api.del(`/sales/interviews/api/knowledge/${id}`);
            load();
        } catch (e) { alert('삭제 실패: ' + e.message); }
    };

    const handleAdd = async (data) => {
        try {
            await api.post(`/sales/interviews/api/projects/${projectId}/knowledge`, data);
            setShowAddForm(false);
            load();
        } catch (e) { alert('추가 실패: ' + e.message); }
    };

    const KNOWLEDGE_TYPE_ICONS = {
        fact: '📌', rule: '📏', formula: '🔢', mapping: '🔗', range: '📊', table: '📋',
    };

    return (
        <div className="p-4 space-y-4">
            {/* 필터 바 */}
            <div className="flex items-center gap-3">
                <select value={domainFilter} onChange={e => setDomainFilter(e.target.value)}
                    className="px-2 py-1.5 border border-gray-300 rounded text-sm">
                    <option value="">전체 도메인</option>
                    {Object.entries(DOMAIN_LABELS).map(([k, v]) => (
                        <option key={k} value={k}>{v}</option>
                    ))}
                </select>
                <select value={verifiedFilter} onChange={e => setVerifiedFilter(e.target.value)}
                    className="px-2 py-1.5 border border-gray-300 rounded text-sm">
                    <option value="">전체</option>
                    <option value="true">검증됨</option>
                    <option value="false">미검증</option>
                </select>
                <button onClick={() => setShowAddForm(true)}
                    className="flex items-center gap-1 px-3 py-1.5 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 ml-auto">
                    <IconPlus className="w-4 h-4" /> 수동 추가
                </button>
            </div>

            {/* 지식 추가 폼 */}
            {showAddForm && (
                <KnowledgeAddForm
                    onSave={handleAdd}
                    onCancel={() => setShowAddForm(false)}
                />
            )}

            {loading ? (
                <div className="flex items-center justify-center h-32">
                    <IconLoader className="w-6 h-6 animate-spin text-blue-500" />
                </div>
            ) : items.length === 0 ? (
                <div className="flex flex-col items-center justify-center h-32 text-gray-400">
                    <IconBrain className="w-8 h-8 mb-2" />
                    <span>추출된 지식이 없습니다</span>
                </div>
            ) : (
                <div className="space-y-2">
                    {items.map(item => (
                        <div key={item.id} className="knowledge-card">
                            <div className="flex items-start justify-between">
                                <div className="flex items-center gap-2">
                                    <span>{KNOWLEDGE_TYPE_ICONS[item.knowledge_type] || '📎'}</span>
                                    <span className={`text-xs font-medium ${item.is_verified ? 'text-green-600' : 'text-yellow-600'}`}>
                                        {item.is_verified ? '검증됨' : '미검증'}
                                    </span>
                                    <span className="text-sm font-medium text-gray-900">{item.title}</span>
                                </div>
                                <div className="flex items-center gap-1">
                                    <button onClick={() => handleVerify(item.id)}
                                        className={`px-2 py-0.5 text-xs rounded ${item.is_verified ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-600 hover:bg-green-50'}`}>
                                        {item.is_verified ? '검증 해제' : '검증'}
                                    </button>
                                    <button onClick={() => handleDelete(item.id)} className="text-red-400 hover:text-red-600">
                                        <IconTrash className="w-3.5 h-3.5" />
                                    </button>
                                </div>
                            </div>
                            <div className="mt-1 text-xs text-gray-500">
                                {DOMAIN_LABELS[item.domain] || item.domain} · {item.knowledge_type} · 출처: {item.source_type}
                            </div>
                            {/* 신뢰도 바 */}
                            <div className="flex items-center gap-2 mt-2">
                                <span className="text-xs text-gray-400">신뢰도</span>
                                <div className="confidence-bar flex-1" style={{ maxWidth: '100px' }}>
                                    <div className="confidence-fill"
                                        style={{
                                            width: `${(item.confidence || 0) * 100}%`,
                                            backgroundColor: item.confidence >= 0.8 ? '#22c55e' : item.confidence >= 0.5 ? '#eab308' : '#ef4444'
                                        }} />
                                </div>
                                <span className="text-xs text-gray-500">{((item.confidence || 0) * 100).toFixed(0)}%</span>
                            </div>
                        </div>
                    ))}
                </div>
            )}
        </div>
    );
}

// ============================================================
// 지식 수동 추가 폼
// ============================================================
function KnowledgeAddForm({ onSave, onCancel }) {
    const [domain, setDomain] = useState('product_classification');
    const [knowledgeType, setKnowledgeType] = useState('fact');
    const [title, setTitle] = useState('');
    const [contentText, setContentText] = useState('');

    const handleSave = () => {
        if (!title.trim()) { alert('제목을 입력하세요.'); return; }
        onSave({
            domain,
            knowledge_type: knowledgeType,
            title: title.trim(),
            content: { text: contentText },
            source_type: 'manual',
            confidence: 1.0,
        });
    };

    return (
        <div className="border border-blue-200 rounded-lg p-4 bg-blue-50 space-y-3">
            <div className="flex gap-3">
                <select value={domain} onChange={e => setDomain(e.target.value)}
                    className="px-2 py-1.5 border border-gray-300 rounded text-sm">
                    {Object.entries(DOMAIN_LABELS).map(([k, v]) => (
                        <option key={k} value={k}>{v}</option>
                    ))}
                </select>
                <select value={knowledgeType} onChange={e => setKnowledgeType(e.target.value)}
                    className="px-2 py-1.5 border border-gray-300 rounded text-sm">
                    <option value="fact">사실 (fact)</option>
                    <option value="rule">규칙 (rule)</option>
                    <option value="formula">수식 (formula)</option>
                    <option value="mapping">매핑 (mapping)</option>
                    <option value="range">범위 (range)</option>
                    <option value="table">테이블 (table)</option>
                </select>
            </div>
            <input type="text" value={title} onChange={e => setTitle(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded text-sm"
                placeholder="지식 제목 (예: 가이드레일 표준 길이)" />
            <textarea value={contentText} onChange={e => setContentText(e.target.value)}
                className="w-full px-3 py-2 border border-gray-300 rounded text-sm" rows={3}
                placeholder="내용을 입력하세요" />
            <div className="flex gap-2 justify-end">
                <button onClick={onCancel} className="px-3 py-1.5 text-sm text-gray-600 hover:text-gray-800">취소</button>
                <button onClick={handleSave} className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded hover:bg-blue-700">추가</button>
            </div>
        </div>
    );
}

// ============================================================
// 좌측: 카테고리 사이드바
// ============================================================
function CategorySidebar({ categories, selectedId, onSelect, onRefresh }) {
    const [showAddRoot, setShowAddRoot] = useState(false);
    const [showAddChildFor, setShowAddChildFor] = useState(null);
    const [newName, setNewName] = useState('');
    const [editingId, setEditingId] = useState(null);
    const [editName, setEditName] = useState('');
    const [expandedRoots, setExpandedRoots] = useState(() => {
        const map = {};
        categories.forEach(c => { map[c.id] = true; });
        return map;
    });

    useEffect(() => {
        setExpandedRoots(prev => {
            const map = { ...prev };
            categories.forEach(c => { if (map[c.id] === undefined) map[c.id] = true; });
            return map;
        });
    }, [categories]);

    const toggleRoot = (id) => {
        setExpandedRoots(prev => ({ ...prev, [id]: !prev[id] }));
    };

    const handleAdd = async (parentId = null) => {
        if (!newName.trim()) return;
        try {
            await api.post('/sales/interviews/api/categories', { name: newName.trim(), parent_id: parentId });
            setNewName('');
            setShowAddRoot(false);
            setShowAddChildFor(null);
            onRefresh();
        } catch (e) { alert('카테고리 생성 실패: ' + e.message); }
    };

    const handleUpdate = async (id) => {
        if (!editName.trim()) return;
        try {
            await api.put(`/sales/interviews/api/categories/${id}`, { name: editName.trim() });
            setEditingId(null);
            onRefresh();
        } catch (e) { alert('수정 실패: ' + e.message); }
    };

    const handleDelete = async (id) => {
        if (!confirm('이 카테고리를 삭제하시겠습니까?\n하위 항목과 질문도 함께 삭제됩니다.')) return;
        try {
            await api.del(`/sales/interviews/api/categories/${id}`);
            onRefresh();
        } catch (e) { alert('삭제 실패: ' + e.message); }
    };

    const renderEditRow = (id) => (
        <div className="flex items-center gap-1 px-2" onClick={e => e.stopPropagation()}>
            <input type="text" value={editName} onChange={e => setEditName(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleUpdate(id); if (e.key === 'Escape') setEditingId(null); }}
                className="flex-1 text-sm border rounded px-1.5 py-0.5" autoFocus />
            <button onClick={() => handleUpdate(id)}
                className="text-xs px-1.5 py-0.5 bg-green-600 text-white rounded hover:bg-green-700">저장</button>
            <button onClick={() => setEditingId(null)}
                className="text-xs px-1.5 py-0.5 text-gray-500 hover:text-gray-700">취소</button>
        </div>
    );

    const renderAddInput = (parentId = null) => (
        <div className="px-3 py-2 border-b border-gray-100 bg-blue-50" style={{ paddingLeft: parentId ? '2rem' : undefined }}>
            <input type="text" value={newName} onChange={e => setNewName(e.target.value)}
                onKeyDown={e => e.key === 'Enter' && handleAdd(parentId)}
                placeholder={parentId ? '중분류명 입력' : '대분류명 입력'} autoFocus
                className="w-full text-sm border border-gray-300 rounded px-2 py-1 mb-1" />
            <div className="flex gap-1 justify-end">
                <button onClick={() => { parentId ? setShowAddChildFor(null) : setShowAddRoot(false); setNewName(''); }}
                    className="text-xs px-2 py-1 text-gray-500 hover:text-gray-700">취소</button>
                <button onClick={() => handleAdd(parentId)}
                    className="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700">추가</button>
            </div>
        </div>
    );

    return (
        <div className="flex flex-col h-full">
            <div className="flex items-center justify-between px-4 py-3 border-b border-gray-200 bg-gray-50">
                <span className="text-sm font-semibold text-gray-700">카테고리</span>
                <button onClick={() => { setShowAddRoot(!showAddRoot); setShowAddChildFor(null); setNewName(''); }}
                    className="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700">
                    + 대분류
                </button>
            </div>

            {showAddRoot && renderAddInput(null)}

            <div className="flex-1 overflow-y-auto">
                {categories.length === 0 && !showAddRoot && (
                    <div className="px-4 py-8 text-center">
                        <p className="text-sm text-gray-400 mb-3">카테고리가 없습니다</p>
                        <button onClick={() => setShowAddRoot(true)}
                            className="text-sm px-3 py-1.5 bg-blue-600 text-white rounded hover:bg-blue-700">
                            + 대분류 추가
                        </button>
                    </div>
                )}
                {categories.map(root => {
                    const hasChildren = root.children && root.children.length > 0;
                    const expanded = expandedRoots[root.id];
                    return (
                        <div key={root.id}>
                            {/* 대분류 (루트) */}
                            {editingId === root.id ? (
                                <div className="px-3 py-2">{renderEditRow(root.id)}</div>
                            ) : (
                                <div className="flex items-center justify-between px-3 py-2 cursor-pointer hover:bg-gray-50 border-b border-gray-100"
                                    onClick={() => hasChildren ? toggleRoot(root.id) : onSelect(root.id)}>
                                    <div className="flex items-center gap-1.5 min-w-0">
                                        {hasChildren && (
                                            <span className="text-xs text-gray-400" style={{ width: '14px', display: 'inline-block' }}>
                                                {expanded ? '▼' : '▶'}
                                            </span>
                                        )}
                                        <span className="text-sm font-medium text-gray-800 truncate">{root.name}</span>
                                    </div>
                                    <div className="flex items-center gap-1.5 flex-shrink-0" onClick={e => e.stopPropagation()}>
                                        <button onClick={() => { setEditingId(root.id); setEditName(root.name); }}
                                            className="text-xs text-blue-600 hover:text-blue-800">수정</button>
                                        <button onClick={() => handleDelete(root.id)}
                                            className="text-xs text-red-500 hover:text-red-700">삭제</button>
                                    </div>
                                </div>
                            )}

                            {/* 중분류 목록 + 하단 추가 버튼 */}
                            {expanded && (
                                <>
                                    {hasChildren && root.children.map(child => (
                                <div key={child.id}>
                                    {editingId === child.id ? (
                                        <div className="py-2" style={{ paddingLeft: '2rem' }}>{renderEditRow(child.id)}</div>
                                    ) : (
                                        <div className={`category-item flex items-center justify-between py-2 pr-3 cursor-pointer ${selectedId === child.id ? 'active' : ''}`}
                                            style={{ paddingLeft: '2rem' }}
                                            onClick={() => onSelect(child.id)}>
                                            <div className="flex items-center gap-2 min-w-0">
                                                <span className="text-xs">📋</span>
                                                <span className="text-sm text-gray-700 truncate">{child.name}</span>
                                            </div>
                                            {selectedId === child.id && (
                                                <div className="flex items-center gap-1 ml-2 flex-shrink-0" onClick={e => e.stopPropagation()}>
                                                    <button onClick={() => { setEditingId(child.id); setEditName(child.name); }}
                                                        className="text-xs text-blue-600 hover:text-blue-800">수정</button>
                                                    <button onClick={() => handleDelete(child.id)}
                                                        className="text-xs text-red-500 hover:text-red-700">삭제</button>
                                                </div>
                                            )}
                                        </div>
                                    )}
                                </div>
                            ))}

                                    {/* 중분류 추가 입력 */}
                                    {showAddChildFor === root.id && renderAddInput(root.id)}

                                    {/* + 중분류 추가 버튼 */}
                                    {showAddChildFor !== root.id && (
                                        <div className="py-1.5 pr-3 border-b border-gray-100" style={{ paddingLeft: '2rem' }}>
                                            <button onClick={() => { setShowAddChildFor(root.id); setShowAddRoot(false); setNewName(''); }}
                                                className="flex items-center gap-1 text-xs text-gray-400 hover:text-blue-600">
                                                <span>+</span> 중분류 추가
                                            </button>
                                        </div>
                                    )}
                                </>
                            )}
                        </div>
                    );
                })}
            </div>
        </div>
    );
}

// ============================================================
// 우측: 메인 콘텐츠 (항목 + 질문)
// ============================================================
function MainContent({ category, onRefresh }) {
    const [showAddTemplate, setShowAddTemplate] = useState(false);
    const [showMdPreview, setShowMdPreview] = useState(false);
    const [mdParsed, setMdParsed] = useState([]);
    const [mdImporting, setMdImporting] = useState(false);
    const fileInputRef = useRef(null);

    const parseMd = (text) => {
        const lines = text.split('\n');
        const result = [];
        let current = null;
        for (const line of lines) {
            const headerMatch = line.match(/^#+\s+(.+)/);
            if (headerMatch) {
                current = { name: headerMatch[1].trim(), questions: [] };
                result.push(current);
                continue;
            }
            const listMatch = line.match(/^[-*]\s+(.+)/);
            if (listMatch && current) {
                current.questions.push(listMatch[1].trim());
            }
        }
        return result.filter(t => t.questions.length > 0);
    };

    const handleFileSelect = (e) => {
        const file = e.target.files[0];
        if (!file) return;
        const reader = new FileReader();
        reader.onload = (ev) => {
            const parsed = parseMd(ev.target.result);
            if (parsed.length === 0) {
                alert('파싱 가능한 항목이 없습니다.\n# 헤더와 - 질문 형식을 확인하세요.');
                return;
            }
            setMdParsed(parsed);
            setShowMdPreview(true);
        };
        reader.readAsText(file);
        e.target.value = '';
    };

    const handleBulkImport = async () => {
        setMdImporting(true);
        try {
            await api.post('/sales/interviews/api/bulk-import', {
                category_id: category.id,
                templates: mdParsed,
            });
            setShowMdPreview(false);
            setMdParsed([]);
            onRefresh();
        } catch (e) { alert('일괄 생성 실패: ' + e.message); }
        finally { setMdImporting(false); }
    };

    if (!category) {
        return (
            <div className="flex items-center justify-center h-full text-gray-400">
                <div className="text-center">
                    <p className="text-lg mb-1">📋</p>
                    <p>카테고리를 선택하세요</p>
                </div>
            </div>
        );
    }

    const templates = category.templates || [];
    const totalMdQuestions = mdParsed.reduce((sum, t) => sum + t.questions.length, 0);

    return (
        <div className="flex flex-col h-full">
            <div className="flex items-center justify-between px-4 py-3 border-b border-gray-200 bg-gray-50">
                <div>
                    <span className="text-sm font-semibold text-gray-700">{category.name}</span>
                    <span className="ml-2 text-xs text-gray-400">{templates.length}개 항목</span>
                </div>
                <div>
                    <input type="file" ref={fileInputRef} accept=".md,.txt" onChange={handleFileSelect} className="hidden" />
                    <button onClick={() => fileInputRef.current?.click()}
                        className="flex items-center gap-1 text-xs px-3 py-1.5 bg-green-600 text-white rounded hover:bg-green-700">
                        <IconUpload className="w-3.5 h-3.5" /> MD 업로드
                    </button>
                </div>
            </div>

            {/* MD 미리보기 */}
            {showMdPreview && (
                <div className="mx-4 mt-3 p-4 bg-green-50 border border-green-200 rounded-lg">
                    <div className="flex items-center justify-between mb-3">
                        <span className="text-sm font-semibold text-green-800">
                            MD 파싱 결과: 항목 {mdParsed.length}개, 질문 {totalMdQuestions}개
                        </span>
                        <button onClick={() => { setShowMdPreview(false); setMdParsed([]); }}
                            className="text-xs text-gray-500 hover:text-gray-700">닫기</button>
                    </div>
                    <div className="space-y-2 max-h-60 overflow-y-auto">
                        {mdParsed.map((tpl, i) => (
                            <div key={i} className="bg-white rounded border border-green-100 p-2">
                                <div className="text-sm font-medium text-gray-800 mb-1">📄 {tpl.name}</div>
                                <ul className="space-y-0.5">
                                    {tpl.questions.map((q, j) => (
                                        <li key={j} className="text-xs text-gray-600 pl-3">• {q}</li>
                                    ))}
                                </ul>
                            </div>
                        ))}
                    </div>
                    <div className="flex gap-2 justify-end mt-3">
                        <button onClick={() => { setShowMdPreview(false); setMdParsed([]); }}
                            className="text-xs px-3 py-1.5 text-gray-500 hover:text-gray-700">취소</button>
                        <button onClick={handleBulkImport} disabled={mdImporting}
                            className="text-xs px-3 py-1.5 bg-green-600 text-white rounded hover:bg-green-700 disabled:opacity-50">
                            {mdImporting ? '생성 중...' : '확인 - 일괄 생성'}
                        </button>
                    </div>
                </div>
            )}

            <div className="flex-1 overflow-y-auto p-4 space-y-4">
                {templates.map(tpl => (
                    <TemplateCard key={tpl.id} template={tpl} onRefresh={onRefresh} />
                ))}

                {templates.length === 0 && !showAddTemplate && (
                    <div className="text-center py-8 text-sm text-gray-400">
                        항목을 추가하여 인터뷰 시나리오를 만드세요
                    </div>
                )}

                {showAddTemplate ? (
                    <AddTemplateForm
                        categoryId={category.id}
                        onCancel={() => setShowAddTemplate(false)}
                        onSaved={() => { setShowAddTemplate(false); onRefresh(); }}
                    />
                ) : (
                    <button onClick={() => setShowAddTemplate(true)}
                        className="text-sm px-3 py-1.5 bg-blue-600 text-white rounded hover:bg-blue-700">
                        + 항목 추가
                    </button>
                )}
            </div>
        </div>
    );
}

// ============================================================
// 항목 카드
// ============================================================
function TemplateCard({ template, onRefresh }) {
    const [editing, setEditing] = useState(false);
    const [editName, setEditName] = useState(template.name);
    const [showAddQuestion, setShowAddQuestion] = useState(false);
    const [confirmPos, setConfirmPos] = useState(null);
    const [deleting, setDeleting] = useState(false);

    const questions = template.questions || [];

    const handleUpdate = async () => {
        if (!editName.trim()) return;
        try {
            await api.put(`/sales/interviews/api/templates/${template.id}`, { name: editName.trim() });
            setEditing(false);
            onRefresh();
        } catch (e) { alert('수정 실패: ' + e.message); }
    };

    const handleDeleteClick = (e) => {
        const rect = e.currentTarget.getBoundingClientRect();
        setConfirmPos({ top: rect.bottom + 4, left: rect.right - 200 });
    };

    const handleDeleteConfirm = async () => {
        setDeleting(true);
        try {
            await api.del(`/sales/interviews/api/templates/${template.id}`);
            onRefresh();
        } catch (e) { alert('삭제 실패: ' + e.message); setDeleting(false); }
        setConfirmPos(null);
    };

    return (
        <div className="template-card" style={{ position: 'relative' }}>
            {/* 항목 헤더 */}
            <div className="flex items-center justify-between px-4 py-2.5 bg-gray-50 rounded-t-lg border-b border-gray-200">
                {editing ? (
                    <div className="flex-1 flex items-center gap-2">
                        <input type="text" value={editName} onChange={e => setEditName(e.target.value)}
                            onKeyDown={e => { if (e.key === 'Enter') handleUpdate(); if (e.key === 'Escape') setEditing(false); }}
                            className="flex-1 text-sm border rounded px-2 py-1" autoFocus />
                        <button onClick={handleUpdate}
                            className="text-xs px-2 py-1 bg-green-600 text-white rounded hover:bg-green-700">저장</button>
                        <button onClick={() => { setEditing(false); setEditName(template.name); }}
                            className="text-xs px-2 py-1 text-gray-500 hover:text-gray-700">취소</button>
                    </div>
                ) : (
                    <>
                        <div className="flex items-center gap-2">
                            <span className="text-sm font-medium text-gray-800">📄 {template.name}</span>
                            <span className="text-xs text-gray-400">({questions.length}개 질문)</span>
                        </div>
                        <div className="flex items-center gap-2">
                            <button onClick={() => { setEditing(true); setEditName(template.name); }}
                                className="text-xs text-blue-600 hover:text-blue-800">수정</button>
                            <button onClick={handleDeleteClick}
                                className="text-xs text-red-500 hover:text-red-700">삭제</button>
                        </div>
                    </>
                )}
            </div>

            {confirmPos && (
                <div className="fixed inset-0" style={{ zIndex: 9998 }} onClick={() => setConfirmPos(null)}>
                    <div onClick={e => e.stopPropagation()}
                        style={{
                            position: 'fixed', top: confirmPos.top, left: confirmPos.left, zIndex: 9999,
                            background: '#fff', border: '1px solid #e5e7eb', borderRadius: '8px',
                            boxShadow: '0 4px 12px rgba(0,0,0,0.15)', padding: '12px 16px', minWidth: '200px',
                        }}>
                        <p style={{ fontSize: '13px', color: '#374151', marginBottom: '4px', fontWeight: 500 }}>"{template.name}" 삭제</p>
                        <p style={{ fontSize: '12px', color: '#6b7280', marginBottom: '10px' }}>하위 질문도 함께 삭제됩니다.</p>
                        <div style={{ display: 'flex', gap: '6px', justifyContent: 'flex-end' }}>
                            <button onClick={() => setConfirmPos(null)}
                                style={{ fontSize: '12px', padding: '4px 10px', color: '#6b7280', cursor: 'pointer', border: '1px solid #d1d5db', borderRadius: '4px', background: '#fff' }}>취소</button>
                            <button onClick={handleDeleteConfirm} disabled={deleting}
                                style={{ fontSize: '12px', padding: '4px 10px', color: '#fff', cursor: 'pointer', border: 'none', borderRadius: '4px', background: deleting ? '#fca5a5' : '#ef4444' }}>
                                {deleting ? '삭제 중...' : '삭제'}
                            </button>
                        </div>
                    </div>
                </div>
            )}

            {/* 질문 목록 */}
            <div className="divide-y divide-gray-100">
                {questions.map(q => (
                    <QuestionItem key={q.id} question={q} onRefresh={onRefresh} />
                ))}
            </div>

            {/* 질문 추가 */}
            <div className="px-4 py-2 border-t border-gray-100">
                {showAddQuestion ? (
                    <AddQuestionForm
                        templateId={template.id}
                        onCancel={() => setShowAddQuestion(false)}
                        onSaved={() => { setShowAddQuestion(false); onRefresh(); }}
                    />
                ) : (
                    <button onClick={() => setShowAddQuestion(true)}
                        className="text-xs text-blue-600 hover:text-blue-800 py-1">
                        + 질문 추가
                    </button>
                )}
            </div>
        </div>
    );
}

// ============================================================
// 질문 행
// ============================================================
function QuestionItem({ question, onRefresh }) {
    const [editing, setEditing] = useState(false);
    const [editText, setEditText] = useState(question.question_text);
    const [confirmPos, setConfirmPos] = useState(null);
    const [deleting, setDeleting] = useState(false);

    const handleUpdate = async () => {
        if (!editText.trim()) return;
        try {
            await api.put(`/sales/interviews/api/questions/${question.id}`, { question_text: editText.trim() });
            setEditing(false);
            onRefresh();
        } catch (e) { alert('수정 실패: ' + e.message); }
    };

    const handleDeleteClick = (e) => {
        const rect = e.currentTarget.getBoundingClientRect();
        setConfirmPos({ top: rect.bottom + 4, left: rect.left });
    };

    const handleDeleteConfirm = async () => {
        setDeleting(true);
        try {
            await api.del(`/sales/interviews/api/questions/${question.id}`);
            onRefresh();
        } catch (e) { alert('삭제 실패: ' + e.message); setDeleting(false); }
        setConfirmPos(null);
    };

    return (
        <div className="question-row px-4 py-2 flex items-center justify-between group hover:bg-gray-50" style={{ position: 'relative' }}>
            {editing ? (
                <div className="flex-1 flex items-center gap-2">
                    <input type="text" value={editText} onChange={e => setEditText(e.target.value)}
                        onKeyDown={e => { if (e.key === 'Enter') handleUpdate(); if (e.key === 'Escape') setEditing(false); }}
                        className="flex-1 text-sm border rounded px-2 py-1" autoFocus />
                    <button onClick={handleUpdate}
                        className="text-xs px-1.5 py-0.5 bg-green-600 text-white rounded hover:bg-green-700">저장</button>
                    <button onClick={() => { setEditing(false); setEditText(question.question_text); }}
                        className="text-xs px-1.5 py-0.5 text-gray-500 hover:text-gray-700">취소</button>
                </div>
            ) : (
                <>
                    <div className="flex items-center gap-2 flex-1 min-w-0">
                        <span className="w-4 h-4 border-2 border-gray-300 rounded flex-shrink-0"></span>
                        <span className="text-sm text-gray-700">{question.question_text}</span>
                        {question.is_required && <span className="text-xs text-red-500">*필수</span>}
                        <button onClick={handleDeleteClick} title="삭제"
                            className="q-delete-x text-xs flex-shrink-0"
                            style={{ color: '#ef4444', cursor: 'pointer' }}>삭제</button>
                    </div>
                    <div className="q-edit-btn items-center gap-2 flex-shrink-0">
                        <button onClick={() => { setEditing(true); setEditText(question.question_text); }}
                            className="text-xs text-blue-600 hover:text-blue-800">수정</button>
                    </div>
                </>
            )}

            {confirmPos && (
                <div className="fixed inset-0" style={{ zIndex: 9998 }} onClick={() => setConfirmPos(null)}>
                    <div onClick={e => e.stopPropagation()}
                        style={{
                            position: 'fixed', top: confirmPos.top, left: confirmPos.left, zIndex: 9999,
                            background: '#fff', border: '1px solid #e5e7eb', borderRadius: '8px',
                            boxShadow: '0 4px 12px rgba(0,0,0,0.15)', padding: '12px 16px', minWidth: '180px',
                        }}>
                        <p style={{ fontSize: '13px', color: '#374151', marginBottom: '10px' }}>이 질문을 삭제할까요?</p>
                        <div style={{ display: 'flex', gap: '6px', justifyContent: 'flex-end' }}>
                            <button onClick={() => setConfirmPos(null)}
                                style={{ fontSize: '12px', padding: '4px 10px', color: '#6b7280', cursor: 'pointer', border: '1px solid #d1d5db', borderRadius: '4px', background: '#fff' }}>취소</button>
                            <button onClick={handleDeleteConfirm} disabled={deleting}
                                style={{ fontSize: '12px', padding: '4px 10px', color: '#fff', cursor: 'pointer', border: 'none', borderRadius: '4px', background: deleting ? '#fca5a5' : '#ef4444' }}>
                                {deleting ? '삭제 중...' : '삭제'}
                            </button>
                        </div>
                    </div>
                </div>
            )}
        </div>
    );
}

// ============================================================
// 항목 추가 폼
// ============================================================
function AddTemplateForm({ categoryId, onCancel, onSaved }) {
    const [name, setName] = useState('');

    const handleSubmit = async () => {
        if (!name.trim()) return;
        try {
            await api.post('/sales/interviews/api/templates', { interview_category_id: categoryId, name: name.trim() });
            onSaved();
        } catch (e) { alert('항목 생성 실패: ' + e.message); }
    };

    return (
        <div className="template-card p-3 bg-blue-50">
            <input type="text" value={name} onChange={e => setName(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleSubmit(); if (e.key === 'Escape') onCancel(); }}
                placeholder="항목명 입력 (예: 견적서 제작)" autoFocus
                className="w-full text-sm border border-gray-300 rounded px-2 py-1.5 mb-2" />
            <div className="flex gap-2 justify-end">
                <button onClick={onCancel} className="text-xs px-3 py-1 text-gray-500 hover:text-gray-700">취소</button>
                <button onClick={handleSubmit} className="text-xs px-3 py-1 bg-blue-600 text-white rounded hover:bg-blue-700">추가</button>
            </div>
        </div>
    );
}

// ============================================================
// 질문 추가 폼
// ============================================================
function AddQuestionForm({ templateId, onCancel, onSaved }) {
    const [text, setText] = useState('');

    const handleSubmit = async () => {
        if (!text.trim()) return;
        try {
            await api.post('/sales/interviews/api/questions', { interview_template_id: templateId, question_text: text.trim() });
            onSaved();
        } catch (e) { alert('질문 생성 실패: ' + e.message); }
    };

    return (
        <div className="flex items-center gap-2">
            <input type="text" value={text} onChange={e => setText(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleSubmit(); if (e.key === 'Escape') onCancel(); }}
                placeholder="질문 내용 입력" autoFocus
                className="flex-1 text-sm border border-gray-300 rounded px-2 py-1" />
            <button onClick={handleSubmit} className="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700">추가</button>
            <button onClick={onCancel} className="text-xs px-2 py-1 text-gray-500 hover:text-gray-700">취소</button>
        </div>
    );
}

// ============================================================
// 인터뷰 실시 모달
// ============================================================
function InterviewSessionModal({ categories, onClose, onComplete }) {
    const [step, setStep] = useState('setup'); // setup → checklist
    const [selectedCategoryId, setSelectedCategoryId] = useState('');
    const [intervieweeName, setIntervieweeName] = useState('');
    const [intervieweeCompany, setIntervieweeCompany] = useState('');
    const [interviewDate, setInterviewDate] = useState(new Date().toISOString().split('T')[0]);
    const [memo, setMemo] = useState('');
    const [session, setSession] = useState(null);
    const [sessionDetail, setSessionDetail] = useState(null);
    const [submitting, setSubmitting] = useState(false);

    const startInterview = async () => {
        if (!selectedCategoryId) { alert('카테고리를 선택하세요'); return; }
        setSubmitting(true);
        try {
            const sess = await api.post('/sales/interviews/api/sessions', {
                interview_category_id: parseInt(selectedCategoryId),
                interviewee_name: intervieweeName,
                interviewee_company: intervieweeCompany,
                interview_date: interviewDate,
                memo: memo,
            });
            setSession(sess);
            const detail = await api.get(`/sales/interviews/api/sessions/${sess.id}`);
            setSessionDetail(detail);
            setStep('checklist');
        } catch (e) { alert('세션 시작 실패: ' + e.message); }
        finally { setSubmitting(false); }
    };

    const handleToggle = async (questionId) => {
        try {
            await api.post('/sales/interviews/api/sessions/toggle-answer', {
                session_id: session.id,
                question_id: questionId,
            });
            const detail = await api.get(`/sales/interviews/api/sessions/${session.id}`);
            setSessionDetail(detail);
        } catch (e) { console.error('토글 실패:', e); }
    };

    const handleComplete = async () => {
        if (!confirm('인터뷰를 완료하시겠습니까?')) return;
        try {
            await api.post(`/sales/interviews/api/sessions/${session.id}/complete`);
            onComplete();
        } catch (e) { alert('완료 실패: ' + e.message); }
    };

    // 답변을 템플릿별로 그룹핑
    const groupedAnswers = sessionDetail ? (() => {
        const groups = {};
        (sessionDetail.answers || []).forEach(a => {
            const tplId = a.interview_template_id;
            if (!groups[tplId]) {
                groups[tplId] = { template: a.template, answers: [] };
            }
            groups[tplId].answers.push(a);
        });
        return Object.values(groups);
    })() : [];

    const totalQ = sessionDetail?.total_questions || 0;
    const answeredQ = sessionDetail?.answered_questions || 0;
    const progress = totalQ > 0 ? Math.round((answeredQ / totalQ) * 100) : 0;

    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center modal-overlay fade-in" onClick={onClose}>
            <div className="bg-white rounded-xl shadow-xl w-full max-w-2xl max-h-[85vh] flex flex-col" onClick={e => e.stopPropagation()}>
                {/* 모달 헤더 */}
                <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200">
                    <h2 className="text-lg font-bold text-gray-900">
                        {step === 'setup' ? '인터뷰 실시' : '체크리스트'}
                    </h2>
                    <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
                        <IconX className="w-5 h-5" />
                    </button>
                </div>

                {/* 모달 본문 */}
                <div className="flex-1 overflow-y-auto px-6 py-4">
                    {step === 'setup' && (
                        <div className="space-y-4">
                            <div>
                                <label className="block text-sm font-medium text-gray-700 mb-1">카테고리 *</label>
                                <select value={selectedCategoryId} onChange={e => setSelectedCategoryId(e.target.value)}
                                    className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm">
                                    <option value="">선택하세요</option>
                                    {categories.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                                </select>
                            </div>
                            <div className="grid grid-cols-2 gap-4">
                                <div>
                                    <label className="block text-sm font-medium text-gray-700 mb-1">면담 상대 이름</label>
                                    <input type="text" value={intervieweeName} onChange={e => setIntervieweeName(e.target.value)}
                                        className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm" placeholder="이름" />
                                </div>
                                <div>
                                    <label className="block text-sm font-medium text-gray-700 mb-1">면담 상대 회사</label>
                                    <input type="text" value={intervieweeCompany} onChange={e => setIntervieweeCompany(e.target.value)}
                                        className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm" placeholder="회사명" />
                                </div>
                            </div>
                            <div>
                                <label className="block text-sm font-medium text-gray-700 mb-1">면담 일자</label>
                                <input type="date" value={interviewDate} onChange={e => setInterviewDate(e.target.value)}
                                    className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm" />
                            </div>
                            <div>
                                <label className="block text-sm font-medium text-gray-700 mb-1">메모</label>
                                <textarea value={memo} onChange={e => setMemo(e.target.value)} rows={3}
                                    className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm" placeholder="메모 (선택사항)" />
                            </div>
                        </div>
                    )}

                    {step === 'checklist' && sessionDetail && (
                        <div className="space-y-4">
                            {/* 진행률 */}
                            <div className="bg-gray-50 rounded-lg p-3">
                                <div className="flex items-center justify-between text-sm mb-1">
                                    <span className="text-gray-600">진행률</span>
                                    <span className="font-medium text-gray-900">{answeredQ}/{totalQ} ({progress}%)</span>
                                </div>
                                <div className="w-full bg-gray-200 rounded-full h-2">
                                    <div className="progress-bar-fill bg-blue-600 h-2 rounded-full" style={{ width: `${progress}%` }}></div>
                                </div>
                            </div>

                            {/* 면담 정보 */}
                            <div className="flex items-center gap-4 text-xs text-gray-500 bg-gray-50 rounded-lg px-3 py-2">
                                {sessionDetail.interviewee_name && (
                                    <span className="flex items-center gap-1"><IconUser className="w-3 h-3" />{sessionDetail.interviewee_name}</span>
                                )}
                                {sessionDetail.interviewee_company && (
                                    <span className="flex items-center gap-1"><IconBuilding className="w-3 h-3" />{sessionDetail.interviewee_company}</span>
                                )}
                                <span className="flex items-center gap-1"><IconCalendar className="w-3 h-3" />{sessionDetail.interview_date}</span>
                            </div>

                            {/* 체크리스트 */}
                            {groupedAnswers.map((group, gi) => (
                                <div key={gi} className="border border-gray-200 rounded-lg">
                                    <div className="px-4 py-2 bg-gray-50 rounded-t-lg border-b border-gray-200">
                                        <span className="text-sm font-medium text-gray-800">{group.template?.name || '항목'}</span>
                                    </div>
                                    <div>
                                        {group.answers.map(a => (
                                            <label key={a.id}
                                                className="flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 cursor-pointer border-b border-gray-100 last:border-b-0">
                                                <input type="checkbox" checked={a.is_checked}
                                                    onChange={() => handleToggle(a.interview_question_id)}
                                                    className="w-4 h-4 text-blue-600 rounded border-gray-300" />
                                                <span className={`text-sm ${a.is_checked ? 'text-gray-400 line-through' : 'text-gray-700'}`}>
                                                    {a.question?.question_text || '질문'}
                                                </span>
                                            </label>
                                        ))}
                                    </div>
                                </div>
                            ))}
                        </div>
                    )}
                </div>

                {/* 모달 하단 */}
                <div className="flex items-center justify-end gap-2 px-6 py-4 border-t border-gray-200 bg-gray-50">
                    {step === 'setup' && (
                        <>
                            <button onClick={onClose} className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800">취소</button>
                            <button onClick={startInterview} disabled={submitting}
                                className="px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50">
                                {submitting ? '시작 중...' : '인터뷰 시작'}
                            </button>
                        </>
                    )}
                    {step === 'checklist' && (
                        <>
                            <button onClick={onClose} className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800">닫기 (계속 진행)</button>
                            <button onClick={handleComplete}
                                className="flex items-center gap-1 px-4 py-2 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700">
                                <IconCheckCircle className="w-4 h-4" /> 인터뷰 완료
                            </button>
                        </>
                    )}
                </div>
            </div>
        </div>
    );
}

// ============================================================
// 인터뷰 기록 모달
// ============================================================
function SessionHistoryModal({ categories, onClose }) {
    const [sessions, setSessions] = useState([]);
    const [loading, setLoading] = useState(true);
    const [selectedSession, setSelectedSession] = useState(null);
    const [sessionDetail, setSessionDetail] = useState(null);

    useEffect(() => {
        (async () => {
            try {
                const data = await api.get('/sales/interviews/api/sessions');
                setSessions(data.data || []);
            } catch (e) { console.error('세션 목록 로드 실패:', e); }
            finally { setLoading(false); }
        })();
    }, []);

    const loadDetail = async (id) => {
        try {
            const detail = await api.get(`/sales/interviews/api/sessions/${id}`);
            setSessionDetail(detail);
            setSelectedSession(id);
        } catch (e) { console.error('상세 로드 실패:', e); }
    };

    // 상세 보기의 답변 그룹핑
    const groupedAnswers = sessionDetail ? (() => {
        const groups = {};
        (sessionDetail.answers || []).forEach(a => {
            const tplId = a.interview_template_id;
            if (!groups[tplId]) {
                groups[tplId] = { template: a.template, answers: [] };
            }
            groups[tplId].answers.push(a);
        });
        return Object.values(groups);
    })() : [];

    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center modal-overlay fade-in" onClick={onClose}>
            <div className="bg-white rounded-xl shadow-xl w-full max-w-3xl max-h-[85vh] flex flex-col" onClick={e => e.stopPropagation()}>
                <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200">
                    <h2 className="text-lg font-bold text-gray-900">
                        {selectedSession ? '인터뷰 상세' : '인터뷰 기록'}
                    </h2>
                    <div className="flex items-center gap-2">
                        {selectedSession && (
                            <button onClick={() => { setSelectedSession(null); setSessionDetail(null); }}
                                className="text-sm text-blue-600 hover:text-blue-800">목록으로</button>
                        )}
                        <button onClick={onClose} className="text-gray-400 hover:text-gray-600">
                            <IconX className="w-5 h-5" />
                        </button>
                    </div>
                </div>

                <div className="flex-1 overflow-y-auto px-6 py-4">
                    {loading && (
                        <div className="flex items-center justify-center py-12">
                            <IconLoader className="w-6 h-6 animate-spin text-blue-500" />
                        </div>
                    )}

                    {!loading && !selectedSession && (
                        <div>
                            {sessions.length === 0 ? (
                                <div className="text-center py-12 text-gray-400">인터뷰 기록이 없습니다</div>
                            ) : (
                                <table className="w-full text-sm">
                                    <thead>
                                        <tr className="text-left text-gray-500 border-b border-gray-200">
                                            <th className="pb-2 font-medium">일자</th>
                                            <th className="pb-2 font-medium">카테고리</th>
                                            <th className="pb-2 font-medium">면담 대상</th>
                                            <th className="pb-2 font-medium">진행률</th>
                                            <th className="pb-2 font-medium">상태</th>
                                            <th className="pb-2 font-medium"></th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        {sessions.map(s => (
                                            <tr key={s.id} className="border-b border-gray-100 hover:bg-gray-50">
                                                <td className="py-2.5">{s.interview_date}</td>
                                                <td className="py-2.5">{s.category?.name || '-'}</td>
                                                <td className="py-2.5">
                                                    {s.interviewee_name || '-'}
                                                    {s.interviewee_company && <span className="text-gray-400 text-xs ml-1">({s.interviewee_company})</span>}
                                                </td>
                                                <td className="py-2.5">
                                                    <span className="text-xs">{s.answered_questions}/{s.total_questions}</span>
                                                </td>
                                                <td className="py-2.5">
                                                    <span className={`text-xs px-2 py-0.5 rounded-full ${
                                                        s.status === 'completed'
                                                            ? 'bg-green-100 text-green-800'
                                                            : 'bg-yellow-100 text-yellow-800'
                                                    }`}>
                                                        {s.status === 'completed' ? '완료' : '진행중'}
                                                    </span>
                                                </td>
                                                <td className="py-2.5">
                                                    <button onClick={() => loadDetail(s.id)}
                                                        className="text-blue-600 hover:text-blue-800 text-xs">상세</button>
                                                </td>
                                            </tr>
                                        ))}
                                    </tbody>
                                </table>
                            )}
                        </div>
                    )}

                    {selectedSession && sessionDetail && (
                        <div className="space-y-4">
                            {/* 세션 정보 */}
                            <div className="bg-gray-50 rounded-lg p-4 grid grid-cols-2 gap-3 text-sm">
                                <div><span className="text-gray-500">카테고리:</span> <span className="font-medium">{sessionDetail.category?.name}</span></div>
                                <div><span className="text-gray-500">면담일:</span> <span className="font-medium">{sessionDetail.interview_date}</span></div>
                                <div><span className="text-gray-500">면담자:</span> <span className="font-medium">{sessionDetail.interviewer?.name || '-'}</span></div>
                                <div><span className="text-gray-500">면담 대상:</span> <span className="font-medium">{sessionDetail.interviewee_name || '-'} {sessionDetail.interviewee_company ? `(${sessionDetail.interviewee_company})` : ''}</span></div>
                                <div><span className="text-gray-500">진행률:</span> <span className="font-medium">{sessionDetail.answered_questions}/{sessionDetail.total_questions}</span></div>
                                <div><span className="text-gray-500">상태:</span>
                                    <span className={`ml-1 text-xs px-2 py-0.5 rounded-full ${sessionDetail.status === 'completed' ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'}`}>
                                        {sessionDetail.status === 'completed' ? '완료' : '진행중'}
                                    </span>
                                </div>
                                {sessionDetail.memo && (
                                    <div className="col-span-2"><span className="text-gray-500">메모:</span> <span>{sessionDetail.memo}</span></div>
                                )}
                            </div>

                            {/* 체크리스트 결과 */}
                            {groupedAnswers.map((group, gi) => (
                                <div key={gi} className="border border-gray-200 rounded-lg">
                                    <div className="px-4 py-2 bg-gray-50 rounded-t-lg border-b border-gray-200">
                                        <span className="text-sm font-medium text-gray-800">{group.template?.name || '항목'}</span>
                                    </div>
                                    <div>
                                        {group.answers.map(a => (
                                            <div key={a.id} className="flex items-center gap-3 px-4 py-2 border-b border-gray-100 last:border-b-0">
                                                {a.is_checked
                                                    ? <IconCheckCircle className="w-4 h-4 text-green-500 flex-shrink-0" />
                                                    : <span className="w-4 h-4 border-2 border-gray-300 rounded flex-shrink-0"></span>
                                                }
                                                <span className={`text-sm ${a.is_checked ? 'text-gray-700' : 'text-gray-400'}`}>
                                                    {a.question?.question_text || '질문'}
                                                </span>
                                            </div>
                                        ))}
                                    </div>
                                </div>
                            ))}
                        </div>
                    )}
                </div>

                <div className="flex items-center justify-end px-6 py-3 border-t border-gray-200 bg-gray-50">
                    <button onClick={onClose} className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800">닫기</button>
                </div>
            </div>
        </div>
    );
}

// ============================================================
// 렌더
// ============================================================
ReactDOM.createRoot(document.getElementById('interview-scenario-root')).render(<InterviewScenarioApp />);
</script>
@endverbatim
@endpush
