@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; } }
</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');

// ============================================================
// 루트 앱
// ============================================================
function InterviewScenarioApp() {
    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 loadTree = useCallback(async () => {
        try {
            const data = await api.get('/sales/interviews/api/tree');
            setTree(data);
            setCategories(data);
            if (!selectedCategoryId && data.length > 0) {
                setSelectedCategoryId(data[0].id);
            }
        } catch (e) {
            console.error('트리 로드 실패:', e);
        } finally {
            setLoading(false);
        }
    }, [selectedCategoryId]);

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

    const selectedCategory = tree.find(c => c.id === selectedCategoryId);

    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={() => 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={() => 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">
                        <IconPlay className="w-4 h-4" /> 인터뷰 실시
                    </button>
                </div>
            </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)}
                />
            )}
        </div>
    );
}

// ============================================================
// 좌측: 카테고리 사이드바
// ============================================================
function CategorySidebar({ categories, selectedId, onSelect, onRefresh }) {
    const [showAdd, setShowAdd] = useState(false);
    const [newName, setNewName] = useState('');
    const [editingId, setEditingId] = useState(null);
    const [editName, setEditName] = useState('');

    const handleAdd = async () => {
        if (!newName.trim()) return;
        try {
            await api.post('/sales/interviews/api/categories', { name: newName.trim() });
            setNewName('');
            setShowAdd(false);
            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); }
    };

    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={() => setShowAdd(!showAdd)}
                    className="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700">
                    + 추가
                </button>
            </div>

            {showAdd && (
                <div className="px-3 py-2 border-b border-gray-100 bg-blue-50">
                    <input type="text" value={newName} onChange={e => setNewName(e.target.value)}
                        onKeyDown={e => e.key === 'Enter' && handleAdd()}
                        placeholder="카테고리명 입력" 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={() => { setShowAdd(false); setNewName(''); }}
                            className="text-xs px-2 py-1 text-gray-500 hover:text-gray-700">취소</button>
                        <button onClick={handleAdd}
                            className="text-xs px-2 py-1 bg-blue-600 text-white rounded hover:bg-blue-700">추가</button>
                    </div>
                </div>
            )}

            <div className="flex-1 overflow-y-auto">
                {categories.length === 0 && !showAdd && (
                    <div className="px-4 py-8 text-center">
                        <p className="text-sm text-gray-400 mb-3">카테고리가 없습니다</p>
                        <button onClick={() => setShowAdd(true)}
                            className="text-sm px-3 py-1.5 bg-blue-600 text-white rounded hover:bg-blue-700">
                            + 카테고리 추가
                        </button>
                    </div>
                )}
                {categories.map(cat => (
                    <div key={cat.id}
                        className={`category-item px-3 py-2.5 cursor-pointer ${selectedId === cat.id ? 'active' : ''}`}
                        onClick={() => onSelect(cat.id)}>
                        {editingId === cat.id ? (
                            <div className="flex items-center gap-1" onClick={e => e.stopPropagation()}>
                                <input type="text" value={editName} onChange={e => setEditName(e.target.value)}
                                    onKeyDown={e => { if (e.key === 'Enter') handleUpdate(cat.id); if (e.key === 'Escape') setEditingId(null); }}
                                    className="flex-1 text-sm border rounded px-1.5 py-0.5" autoFocus />
                                <button onClick={() => handleUpdate(cat.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>
                        ) : (
                            <div className="flex items-center justify-between">
                                <span className="text-sm text-gray-700 truncate">{cat.name}</span>
                                {selectedId === cat.id && (
                                    <div className="flex items-center gap-1 ml-2 flex-shrink-0" onClick={e => e.stopPropagation()}>
                                        <button onClick={() => { setEditingId(cat.id); setEditName(cat.name); }}
                                            className="text-xs text-blue-600 hover:text-blue-800">수정</button>
                                        <button onClick={() => handleDelete(cat.id)}
                                            className="text-xs text-red-500 hover:text-red-700">삭제</button>
                                    </div>
                                )}
                            </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
