/**
 * issues-dashboard.js — 부적합 현황판 페이지 스크립트
 */

let currentUser = null;
let allIssues = [];
let projects = [];
let filteredIssues = [];

// 애니메이션 함수들
function animateHeaderAppearance() {
    const header = document.getElementById('commonHeader');
    if (header) {
        header.classList.add('header-fade-in');
    }
}

function animateContentAppearance() {
    const content = document.querySelector('.content-fade-in');
    if (content) {
        content.classList.add('visible');
    }
}

// 페이지 초기화
async function initializeDashboard() {
    try {
        // 인증 확인
        currentUser = await window.authManager.checkAuth();
        if (!currentUser) {
            showLoginScreen();
            return;
        }

        // 페이지 권한 확인
        window.pagePermissionManager.setUser(currentUser);
        await window.pagePermissionManager.loadPagePermissions();

        if (!window.pagePermissionManager.canAccessPage('issues_dashboard')) {
            alert('현황판 접근 권한이 없습니다.');
            window.location.href = '/';
            return;
        }

        // 공통 헤더 초기화
        if (window.commonHeader) {
            await window.commonHeader.init(currentUser, 'issues_dashboard');
            setTimeout(() => animateHeaderAppearance(), 100);
        }

        // 데이터 로드
        await Promise.all([
            loadProjects(),
            loadInProgressIssues()
        ]);

        updateDashboard();
        hideLoadingScreen();

    } catch (error) {
        console.error('대시보드 초기화 실패:', error);
        alert('대시보드를 불러오는데 실패했습니다.');
        hideLoadingScreen();
    }
}

// 로딩 스크린 관리
function hideLoadingScreen() {
    document.getElementById('loadingScreen').style.display = 'none';
}

function showLoginScreen() {
    document.getElementById('loadingScreen').style.display = 'none';
    document.getElementById('loginScreen').classList.remove('hidden');
}

// 데이터 로드 함수들
async function loadProjects() {
    try {
        const apiUrl = window.API_BASE_URL || '/api';
        const response = await fetch(`${apiUrl}/projects/`, {
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            }
        });

        if (response.ok) {
            projects = await response.json();
            updateProjectFilter();
        } else {
            throw new Error('프로젝트 목록을 불러올 수 없습니다.');
        }
    } catch (error) {
        console.error('프로젝트 로드 실패:', error);
    }
}

async function loadInProgressIssues() {
    try {
        const response = await fetch('/api/issues/admin/all', {
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            }
        });

        if (response.ok) {
            const allData = await response.json();
            // 진행 중 상태만 필터링
            allIssues = allData.filter(issue => issue.review_status === 'in_progress');
            filteredIssues = [...allIssues];
        } else {
            throw new Error('부적합 목록을 불러올 수 없습니다.');
        }
    } catch (error) {
        console.error('부적합 로드 실패:', error);
    }
}

// 프로젝트 필터 업데이트
function updateProjectFilter() {
    const projectFilter = document.getElementById('projectFilter');
    projectFilter.innerHTML = '<option value="">전체 프로젝트</option>';

    projects.forEach(project => {
        const option = document.createElement('option');
        option.value = project.id;
        option.textContent = project.project_name;
        projectFilter.appendChild(option);
    });
}

// 대시보드 업데이트
function updateDashboard() {
    updateStatistics();
    updateProjectCards();
}

// 통계 업데이트
function updateStatistics() {
    const today = new Date().toDateString();

    // 오늘 신규 (오늘 수신함에서 진행중으로 넘어온 것들)
    const todayIssues = allIssues.filter(issue =>
        issue.reviewed_at && new Date(issue.reviewed_at).toDateString() === today
    );

    // 완료 대기 (완료 신청이 된 것들)
    const pendingCompletionIssues = allIssues.filter(issue =>
        issue.completion_requested_at && issue.review_status === 'in_progress'
    );

    // 지연 중 (마감일이 지난 것들)
    const overdueIssues = allIssues.filter(issue => {
        if (!issue.expected_completion_date) return false;
        const expectedDate = new Date(issue.expected_completion_date);
        const now = new Date();
        return expectedDate < now; // 마감일 지남
    });

    document.getElementById('totalInProgress').textContent = allIssues.length;
    document.getElementById('todayNew').textContent = todayIssues.length;
    document.getElementById('pendingCompletion').textContent = pendingCompletionIssues.length;
    document.getElementById('overdue').textContent = overdueIssues.length;
}

// 이슈 카드 업데이트 (관리함 스타일 - 날짜별 그룹화)
function updateProjectCards() {
    const container = document.getElementById('projectDashboard');
    const emptyState = document.getElementById('emptyState');

    if (filteredIssues.length === 0) {
        container.innerHTML = '';
        emptyState.classList.remove('hidden');
        return;
    }

    emptyState.classList.add('hidden');

    // 날짜별로 그룹화 (관리함 진입일 기준)
    const groupedByDate = {};
    const dateObjects = {}; // 정렬용 Date 객체 저장

    filteredIssues.forEach(issue => {
        // reviewed_at이 있으면 관리함 진입일, 없으면 report_date 사용
        const dateToUse = issue.reviewed_at || issue.report_date;
        const dateObj = new Date(dateToUse);
        const dateKey = dateObj.toLocaleDateString('ko-KR');

        if (!groupedByDate[dateKey]) {
            groupedByDate[dateKey] = [];
            dateObjects[dateKey] = dateObj;
        }
        groupedByDate[dateKey].push(issue);
    });

    // 날짜별 그룹 생성
    const dateGroups = Object.keys(groupedByDate)
        .sort((a, b) => dateObjects[b] - dateObjects[a]) // 최신순
        .map(dateKey => {
            const issues = groupedByDate[dateKey];
            const formattedDate = dateObjects[dateKey].toLocaleDateString('ko-KR', {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit'
            }).replace(/\./g, '. ').trim();

            return `
                <div class="date-group mb-6">
                    <div class="date-header flex items-center justify-between p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition-colors" onclick="toggleDateGroup('${dateKey}')">
                        <div class="flex items-center space-x-3">
                            <i class="fas fa-chevron-down transition-transform duration-200" id="chevron-${dateKey}"></i>
                            <span class="font-semibold text-gray-800">${formattedDate}</span>
                            <span class="text-sm text-gray-500">(${issues.length}건)</span>
                            <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">관리함 진입일</span>
                        </div>
                    </div>
                    <div class="collapse-content mt-4" id="content-${dateKey}">
                        <div class="grid grid-cols-1 gap-4">
                            ${issues.map(issue => createIssueCard(issue)).join('')}
                        </div>
                    </div>
                </div>
            `;
        }).join('');

    container.innerHTML = dateGroups;
}

// getIssueTitle, getIssueDetail은 issue-helpers.js에서 제공됨

// 이슈 카드 생성 (관리함 진행 중 스타일, 읽기 전용)
function createIssueCard(issue) {
    const project = projects.find(p => p.id === issue.project_id);
    const projectName = project ? project.project_name : '미지정';

    // getDepartmentText, getCategoryText는 issue-helpers.js에서 제공됨

    // 완료 반려 내용 포맷팅
    const formatRejectionContent = (issue) => {
        // 1. 새 필드에서 확인
        if (issue.completion_rejection_reason) {
            const rejectedAt = issue.completion_rejected_at
                ? new Date(issue.completion_rejected_at).toLocaleString('ko-KR', {
                    year: 'numeric',
                    month: '2-digit',
                    day: '2-digit',
                    hour: '2-digit',
                    minute: '2-digit'
                })
                : '';

            return rejectedAt
                ? `[${rejectedAt}] ${issue.completion_rejection_reason}`
                : issue.completion_rejection_reason;
        }

        // 2. 기존 데이터에서 패턴 추출 (마이그레이션 전 데이터용)
        if (issue.management_comment) {
            const rejectionPattern = /\[완료 반려[^\]]*\][^\n]*/g;
            const rejections = issue.management_comment.match(rejectionPattern);
            return rejections ? rejections.join('\n') : '';
        }

        return '';
    };

    // solution 파싱 및 카드 형식으로 표시
    const parseSolutionOpinions = (solution, issue) => {
        let html = '';

        // 1. 수신함/관리함 내용 표시 - 항상 표시
        let rawManagementContent = issue.management_comment || issue.final_description || '';

        // 기존 데이터에서 완료 반려 패턴 제거 (마이그레이션용)
        rawManagementContent = rawManagementContent.replace(/\[완료 반려[^\]]*\][^\n]*\n*/g, '').trim();

        // 기본 텍스트들 필터링
        const defaultTexts = [
            '중복작업 신고용',
            '상세 내용 없음',
            '자재 누락',
            '설계 오류',
            '반입 불량',
            '검사 누락',
            '기타',
            '부적합명',
            '상세내용',
            '상세 내용'
        ];

        const filteredLines = rawManagementContent.split('\n').filter(line => {
            const trimmed = line.trim();
            if (!trimmed) return false;
            if (defaultTexts.includes(trimmed)) return false;
            return true;
        });

        const managementContent = filteredLines.join('\n').trim();

        const displayContent = managementContent ? managementContent : '확정된 해결 방안 없음';
        const contentStyle = managementContent ? 'text-red-700' : 'text-red-400 italic';

        html += `
            <div class="mb-2 bg-gradient-to-r from-red-50 to-pink-50 border-red-300 rounded-lg border-l-4 p-2 shadow-sm">
                <div class="text-sm ${contentStyle} leading-relaxed px-2 whitespace-pre-wrap">
                    ${displayContent}
                </div>
            </div>
        `;

        // 2. 해결 방안 의견들 표시
        if (!solution || solution.trim() === '') {
            return html;
        }

        // 구분선으로 의견들을 분리
        const opinions = solution.split(/─{30,}/);

        html += opinions.map((opinion, opinionIndex) => {
            const trimmed = opinion.trim();
            if (!trimmed) return '';

            // [작성자] (날짜시간) 패턴 매칭
            const headerMatch = trimmed.match(/^\[([^\]]+)\]\s*\(([^)]+)\)/);

            if (headerMatch) {
                const author = headerMatch[1];
                const datetime = headerMatch[2];

                // 댓글과 본문 분리
                const lines = trimmed.substring(headerMatch[0].length).trim().split('\n');
                let mainContent = '';
                let comments = [];
                let currentCommentIndex = -1;

                for (const line of lines) {
                    if (line.match(/^\s*└/)) {
                        const commentMatch = line.match(/└\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                        if (commentMatch) {
                            comments.push({
                                author: commentMatch[1],
                                datetime: commentMatch[2],
                                content: commentMatch[3],
                                replies: []
                            });
                            currentCommentIndex = comments.length - 1;
                        }
                    }
                    else if (line.match(/^\s*↳/)) {
                        const replyMatch = line.match(/↳\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                        if (replyMatch && currentCommentIndex >= 0) {
                            comments[currentCommentIndex].replies.push({
                                author: replyMatch[1],
                                datetime: replyMatch[2],
                                content: replyMatch[3]
                            });
                        }
                    } else {
                        mainContent += (mainContent ? '\n' : '') + line;
                    }
                }

                // 색상 스킴
                const colorSchemes = [
                    'bg-gradient-to-r from-green-50 to-emerald-50 border-green-300',
                    'bg-gradient-to-r from-blue-50 to-cyan-50 border-blue-300',
                    'bg-gradient-to-r from-purple-50 to-pink-50 border-purple-300',
                    'bg-gradient-to-r from-orange-50 to-yellow-50 border-orange-300',
                    'bg-gradient-to-r from-indigo-50 to-violet-50 border-indigo-300'
                ];
                const colorScheme = colorSchemes[opinionIndex % colorSchemes.length];

                const isOwnOpinion = currentUser && (author === currentUser.full_name || author === currentUser.username);

                return `
                    <div class="mb-1.5 ${colorScheme} rounded-lg border-l-4 p-2 shadow-sm hover:shadow-md transition-shadow">
                        <div class="flex items-start justify-between mb-1">
                            <div class="flex items-center gap-2">
                                <div class="w-5 h-5 bg-gradient-to-br from-blue-500 to-blue-600 rounded-full flex items-center justify-center text-white text-xs font-bold shadow">
                                    ${author.charAt(0)}
                                </div>
                                <div>
                                    <span class="text-xs font-semibold text-gray-800">${author}</span>
                                    <div class="flex items-center gap-1 text-xs text-gray-500">
                                        <i class="fas fa-clock text-xs"></i>
                                        <span class="text-xs">${datetime}</span>
                                    </div>
                                </div>
                            </div>
                            <div class="flex items-center gap-1">
                                <button onclick="openCommentModal(${issue.id}, ${opinionIndex})"
                                        class="bg-blue-100 hover:bg-blue-200 text-blue-700 px-2 py-1 rounded text-xs transition-colors flex items-center gap-1"
                                        title="댓글 달기">
                                    <i class="fas fa-comment text-xs"></i>
                                    <span>댓글</span>
                                </button>
                                ${isOwnOpinion ? `
                                    <button onclick="editOpinion(${issue.id}, ${opinionIndex})"
                                            class="bg-green-100 hover:bg-green-200 text-green-700 px-2 py-1 rounded text-xs transition-colors flex items-center gap-1"
                                            title="수정">
                                        <i class="fas fa-edit text-xs"></i>
                                        <span>수정</span>
                                    </button>
                                    <button onclick="deleteOpinion(${issue.id}, ${opinionIndex})"
                                            class="bg-red-100 hover:bg-red-200 text-red-700 px-2 py-1 rounded text-xs transition-colors flex items-center gap-1"
                                            title="삭제">
                                        <i class="fas fa-trash text-xs"></i>
                                        <span>삭제</span>
                                    </button>
                                ` : ''}
                            </div>
                        </div>
                        <div class="text-sm text-gray-700 leading-relaxed pl-7 whitespace-pre-wrap">${mainContent}</div>

                        ${comments.length > 0 ? `
                            <div class="mt-2 pl-7">
                                <button onclick="toggleComments(${issue.id}, ${opinionIndex})"
                                        class="bg-gray-100 hover:bg-gray-200 text-gray-700 px-3 py-1.5 rounded-lg text-xs flex items-center gap-2 transition-colors">
                                    <i class="fas fa-chevron-down transition-transform text-xs" id="comment-chevron-${issue.id}-${opinionIndex}"></i>
                                    <i class="fas fa-comments text-xs"></i>
                                    <span class="font-medium">댓글 ${comments.length}개 보기</span>
                                </button>
                                <div id="comments-${issue.id}-${opinionIndex}" class="hidden mt-2 space-y-1.5">
                                    ${comments.map((comment, commentIndex) => {
                                        const isOwnComment = currentUser && (comment.author === currentUser.full_name || comment.author === currentUser.username);
                                        return `
                                        <div class="bg-white bg-opacity-80 rounded-lg p-2 text-xs border border-gray-200">
                                            <div class="flex items-start justify-between mb-1">
                                                <div class="flex items-center gap-1.5">
                                                    <div class="w-4 h-4 bg-gray-400 rounded-full flex items-center justify-center text-white text-xs font-bold">
                                                        ${comment.author.charAt(0)}
                                                    </div>
                                                    <span class="font-semibold text-gray-800">${comment.author}</span>
                                                    <span class="text-gray-400">·</span>
                                                    <span class="text-gray-500">${comment.datetime}</span>
                                                </div>
                                                <div class="flex items-center gap-1">
                                                    <button onclick="openReplyModal(${issue.id}, ${opinionIndex}, ${commentIndex})"
                                                            class="bg-blue-50 hover:bg-blue-100 text-blue-600 px-1.5 py-0.5 rounded text-xs transition-colors flex items-center gap-0.5"
                                                            title="답글">
                                                        <i class="fas fa-reply text-xs"></i>
                                                        <span>답글</span>
                                                    </button>
                                                    ${isOwnComment ? `
                                                        <button onclick="editComment(${issue.id}, ${opinionIndex}, ${commentIndex})"
                                                                class="bg-green-50 hover:bg-green-100 text-green-600 px-1.5 py-0.5 rounded text-xs transition-colors"
                                                                title="수정">
                                                            <i class="fas fa-edit text-xs"></i>
                                                        </button>
                                                        <button onclick="deleteComment(${issue.id}, ${opinionIndex}, ${commentIndex})"
                                                                class="bg-red-50 hover:bg-red-100 text-red-600 px-1.5 py-0.5 rounded text-xs transition-colors"
                                                                title="삭제">
                                                            <i class="fas fa-trash text-xs"></i>
                                                        </button>
                                                    ` : ''}
                                                </div>
                                            </div>
                                            <div class="text-gray-700 pl-5">${comment.content}</div>

                                            ${comment.replies && comment.replies.length > 0 ? `
                                                <div class="mt-2 ml-4 space-y-1 border-l-2 border-blue-200 pl-2">
                                                    ${comment.replies.map((reply, replyIndex) => {
                                                        const isOwnReply = currentUser && (reply.author === currentUser.full_name || reply.author === currentUser.username);
                                                        return `
                                                        <div class="bg-blue-50 bg-opacity-50 rounded p-1.5 text-xs">
                                                            <div class="flex items-start justify-between mb-0.5">
                                                                <div class="flex items-center gap-1">
                                                                    <i class="fas fa-reply text-blue-400 text-xs"></i>
                                                                    <div class="w-3 h-3 bg-blue-400 rounded-full flex items-center justify-center text-white" style="font-size: 8px;">
                                                                        ${reply.author.charAt(0)}
                                                                    </div>
                                                                    <span class="font-semibold text-gray-800">${reply.author}</span>
                                                                    <span class="text-gray-400">·</span>
                                                                    <span class="text-gray-500">${reply.datetime}</span>
                                                                </div>
                                                                ${isOwnReply ? `
                                                                    <div class="flex items-center gap-0.5">
                                                                        <button onclick="editReply(${issue.id}, ${opinionIndex}, ${commentIndex}, ${replyIndex})"
                                                                                class="bg-green-50 hover:bg-green-100 text-green-600 px-1 py-0.5 rounded text-xs transition-colors"
                                                                                title="수정">
                                                                            <i class="fas fa-edit" style="font-size: 9px;"></i>
                                                                        </button>
                                                                        <button onclick="deleteReply(${issue.id}, ${opinionIndex}, ${commentIndex}, ${replyIndex})"
                                                                                class="bg-red-50 hover:bg-red-100 text-red-600 px-1 py-0.5 rounded text-xs transition-colors"
                                                                                title="삭제">
                                                                            <i class="fas fa-trash" style="font-size: 9px;"></i>
                                                                        </button>
                                                                    </div>
                                                                ` : ''}
                                                            </div>
                                                            <div class="text-gray-600 pl-4">${reply.content}</div>
                                                        </div>
                                                        `;
                                                    }).join('')}
                                                </div>
                                            ` : ''}
                                        </div>
                                        `;
                                    }).join('')}
                                </div>
                            </div>
                        ` : ''}
                    </div>
                `;
            } else {
                return `
                    <div class="mb-1.5 bg-gray-50 rounded-lg border-l-4 border-gray-300 p-2">
                        <div class="text-sm text-gray-700 leading-relaxed whitespace-pre-wrap">${trimmed}</div>
                    </div>
                `;
            }
        }).join('');

        return html;
    };

    // 날짜 포맷팅
    const formatKSTDate = (dateStr) => {
        if (!dateStr) return '-';
        const date = new Date(dateStr);
        return date.toLocaleDateString('ko-KR', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit'
        });
    };

    // 상태 체크 함수들
    const getIssueStatus = () => {
        if (issue.review_status === 'completed') return 'completed';
        if (issue.completion_requested_at) return 'pending_completion';

        if (issue.expected_completion_date) {
            const expectedDate = new Date(issue.expected_completion_date);
            const now = new Date();
            const diffDays = (expectedDate - now) / (1000 * 60 * 60 * 24);

            if (diffDays < 0) return 'overdue';
            if (diffDays <= 3) return 'urgent';
        }

        return 'in_progress';
    };

    const getStatusConfig = (status) => {
        const configs = {
            'in_progress': {
                text: '진행 중',
                bgColor: 'bg-gradient-to-r from-blue-500 to-blue-600',
                icon: 'fas fa-cog fa-spin',
                dotColor: 'bg-white'
            },
            'urgent': {
                text: '긴급',
                bgColor: 'bg-gradient-to-r from-orange-500 to-orange-600',
                icon: 'fas fa-exclamation-triangle',
                dotColor: 'bg-white'
            },
            'overdue': {
                text: '지연됨',
                bgColor: 'bg-gradient-to-r from-red-500 to-red-600',
                icon: 'fas fa-clock',
                dotColor: 'bg-white'
            },
            'pending_completion': {
                text: '완료 대기',
                bgColor: 'bg-gradient-to-r from-purple-500 to-purple-600',
                icon: 'fas fa-hourglass-half',
                dotColor: 'bg-white'
            },
            'completed': {
                text: '완료됨',
                bgColor: 'bg-gradient-to-r from-green-500 to-green-600',
                icon: 'fas fa-check-circle',
                dotColor: 'bg-white'
            }
        };
        return configs[status] || configs['in_progress'];
    };

    const currentStatus = getIssueStatus();
    const statusConfig = getStatusConfig(currentStatus);

    return `
        <div class="issue-card bg-white rounded-xl border border-gray-200 p-5 hover:shadow-xl hover:border-blue-300 transition-all duration-300 transform hover:-translate-y-1">
            <!-- 헤더 -->
            <div class="flex justify-between items-start mb-4">
                <div class="flex flex-col space-y-2 flex-1">
                    <div class="flex items-center space-x-2">
                        <span class="text-xl font-bold bg-gradient-to-r from-blue-600 to-blue-800 bg-clip-text text-transparent">No.${issue.project_sequence_no || '-'}</span>
                        <div class="w-2 h-2 bg-blue-500 rounded-full animate-pulse shadow-sm"></div>
                        <span class="text-sm text-gray-600">${projectName}</span>
                    </div>
                    <div class="bg-blue-50 px-3 py-1.5 rounded-lg border-l-4 border-blue-400">
                        <h3 class="text-base font-bold text-blue-900">${getIssueTitle(issue)}</h3>
                    </div>
                </div>
                <div class="flex flex-col items-end space-y-2 ml-4">
                    <div class="flex items-center space-x-3">
                        <div class="flex items-center space-x-2 ${statusConfig.bgColor} text-white px-4 py-1.5 rounded-full shadow-md">
                            <div class="w-2 h-2 ${statusConfig.dotColor} rounded-full animate-pulse"></div>
                            <span class="text-xs font-bold">${statusConfig.text}</span>
                            <i class="${statusConfig.icon} text-xs"></i>
                        </div>
                        <div class="bg-gray-100 px-3 py-1 rounded-full">
                            <span class="text-xs text-gray-600 font-medium">발생: ${formatKSTDate(issue.report_date)}</span>
                        </div>
                    </div>
                    <div class="flex items-center space-x-2">
                        <span class="inline-flex items-center bg-gradient-to-r from-yellow-400 to-orange-400 text-white px-2 py-1 rounded-full text-xs font-medium shadow-sm">
                            <i class="fas fa-tag mr-1"></i>
                            ${getCategoryText(issue.category || issue.final_category)}
                        </span>
                    </div>
                </div>
            </div>

            <!-- 2x2 그리드 -->
            <div class="grid grid-cols-2 gap-4 text-sm">
                <!-- 첫 번째 행: 상세 내용 | 신고자/담당/마감 -->
                <div>
                    <div class="flex items-center mb-2">
                        <i class="fas fa-align-left text-gray-500 mr-2"></i>
                        <span class="text-gray-600 font-medium text-sm">상세 내용</span>
                    </div>
                    <div class="bg-gray-50 rounded-lg p-3 border border-gray-200 min-h-[80px] max-h-[120px] overflow-y-auto">
                        <div class="text-gray-600 text-sm leading-relaxed italic">
                            ${getIssueDetail(issue)}
                        </div>
                    </div>
                </div>
                <div>
                    <div class="flex items-center mb-2">
                        <i class="fas fa-user-clock text-purple-500 mr-2"></i>
                        <span class="text-gray-600 font-medium text-sm">신고자 & 담당 & 마감</span>
                    </div>
                    <div class="grid grid-cols-3 gap-2">
                        <div class="bg-blue-50 rounded-lg p-2 border border-blue-200">
                            <div class="flex items-center justify-center mb-1">
                                <i class="fas fa-user-edit text-blue-500 text-xs mr-1"></i>
                                <span class="text-blue-600 text-xs font-medium">신고자</span>
                            </div>
                            <div class="text-blue-800 font-semibold text-xs text-center">${issue.reporter?.full_name || issue.reporter?.username || '-'}</div>
                        </div>
                        <div class="bg-purple-50 rounded-lg p-2 border border-purple-200">
                            <div class="flex items-center justify-center mb-1">
                                <i class="fas fa-user text-purple-500 text-xs mr-1"></i>
                                <span class="text-purple-600 text-xs font-medium">담당자</span>
                            </div>
                            <div class="text-purple-800 font-semibold text-xs text-center">${issue.responsible_person || '-'}</div>
                        </div>
                        <div class="bg-orange-50 rounded-lg p-2 border border-orange-200 relative">
                            <div class="flex items-center justify-center mb-1">
                                <i class="fas fa-calendar-alt text-orange-500 text-xs mr-1"></i>
                                <span class="text-orange-600 text-xs font-medium">마감</span>
                            </div>
                            <div class="text-orange-800 font-semibold text-xs text-center">${formatKSTDate(issue.expected_completion_date)}</div>
                        </div>
                    </div>
                    ${currentStatus === 'in_progress' || currentStatus === 'urgent' || currentStatus === 'overdue' ? `
                        <div class="flex justify-end">
                            <button onclick="openCompletionRequestModal(${issue.id})"
                                    class="mt-2 bg-green-500 hover:bg-green-600 text-white text-xs px-4 py-1.5 rounded-lg transition-colors shadow-sm">
                                <i class="fas fa-check text-xs mr-1"></i>완료신청
                            </button>
                        </div>
                    ` : ''}
                </div>

                <!-- 두 번째 행: 해결 방안 | 이미지 -->
                <div>
                    <div class="flex items-center justify-between mb-2">
                        <div class="flex items-center">
                            <i class="fas fa-lightbulb text-green-500 mr-2"></i>
                            <span class="text-gray-600 font-medium text-sm">해결 방안</span>
                        </div>
                        <button onclick="openOpinionModal(${issue.id})" class="bg-green-500 hover:bg-green-600 text-white text-xs px-3 py-1 rounded-full transition-colors shadow-sm">
                            <i class="fas fa-comment-medical text-xs mr-1"></i>의견 제시
                        </button>
                    </div>
                    <div class="bg-white rounded-lg p-3 border border-green-200 min-h-[180px] max-h-[280px] overflow-y-auto">
                        ${parseSolutionOpinions(issue.solution, issue)}
                    </div>
                </div>
                <div>
                    <div class="flex items-center mb-2">
                        <i class="fas fa-camera text-blue-500 mr-2"></i>
                        <span class="text-gray-600 font-medium text-sm">이미지</span>
                    </div>
                    <div class="flex flex-wrap gap-3 justify-center">
                        ${(() => {
                            const photos = [
                                issue.photo_path,
                                issue.photo_path2,
                                issue.photo_path3,
                                issue.photo_path4,
                                issue.photo_path5
                            ].filter(p => p);

                            if (photos.length === 0) {
                                return `
                                    <div class="w-40 h-40 bg-gradient-to-br from-gray-50 to-gray-100 rounded-lg border-2 border-gray-200 flex items-center justify-center">
                                        <i class="fas fa-image text-gray-400 text-2xl opacity-50"></i>
                                    </div>
                                `;
                            }

                            return photos.map((path, idx) => `
                                <div class="relative w-40 h-40 rounded-lg border-2 border-blue-200 overflow-hidden cursor-pointer hover:shadow-lg hover:scale-105 transition-all duration-200" onclick="openPhotoModal('${path}')">
                                    <img src="${path}" alt="부적합 사진 ${idx + 1}" class="w-full h-full object-cover" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                                    <div class="absolute inset-0 bg-gradient-to-br from-blue-50 to-blue-100 flex items-center justify-center" style="display: none;">
                                        <i class="fas fa-image text-blue-500 text-2xl"></i>
                                    </div>
                                    <div class="absolute -top-1 -right-1 w-4 h-4 bg-green-500 rounded-full border-2 border-white"></div>
                                </div>
                            `).join('');
                        })()}
                    </div>

                    <!-- 완료 반려 내용 표시 -->
                    ${(() => {
                        const rejection = formatRejectionContent(issue);
                        if (!rejection) return '';

                        return `
                            <div class="mt-2 bg-gradient-to-r from-orange-50 to-red-50 border-orange-400 rounded-lg border-l-4 p-2 shadow-sm">
                                <div class="flex items-center mb-1">
                                    <div class="w-5 h-5 bg-gradient-to-br from-orange-500 to-red-600 rounded-full flex items-center justify-center text-white text-xs font-bold shadow">
                                        <i class="fas fa-exclamation-triangle text-xs"></i>
                                    </div>
                                    <span class="text-xs font-semibold text-orange-800 ml-2">완료 반려 내역</span>
                                </div>
                                <div class="text-sm text-orange-700 leading-relaxed pl-7 whitespace-pre-wrap">${rejection}</div>
                            </div>
                        `;
                    })()}

                    ${currentStatus === 'pending_completion' ? `
                        <div class="mt-2 flex justify-center">
                            <button onclick="openRejectionModal(${issue.id})"
                                    class="bg-red-500 hover:bg-red-600 text-white text-xs px-4 py-1.5 rounded-lg transition-colors shadow-sm">
                                <i class="fas fa-times-circle text-xs mr-1"></i>완료 신청 반려
                            </button>
                        </div>
                    ` : ''}
                </div>
            </div>
        </div>
    `;
}

// openPhotoModal, closePhotoModal은 photo-modal.js에서 제공됨

// ESC 키로 모달 닫기
document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape') {
        closePhotoModal();
        closeRejectionModal();
        closeOpinionModal();
        closeCompletionRequestModal();
        closeCommentModal();
        closeEditOpinionModal();
        closeReplyModal();
        closeEditCommentModal();
        closeEditReplyModal();
    }
});

// 날짜 그룹 토글 기능
function toggleDateGroup(dateKey) {
    const content = document.getElementById(`content-${dateKey}`);
    const chevron = document.getElementById(`chevron-${dateKey}`);

    if (content.style.display === 'none') {
        content.style.display = 'block';
        chevron.classList.remove('fa-chevron-right');
        chevron.classList.add('fa-chevron-down');
    } else {
        content.style.display = 'none';
        chevron.classList.remove('fa-chevron-down');
        chevron.classList.add('fa-chevron-right');
    }
}

// 필터 및 정렬 함수들
function filterByProject() {
    const projectId = document.getElementById('projectFilter').value;

    if (projectId) {
        filteredIssues = allIssues.filter(issue => issue.project_id == projectId);
    } else {
        filteredIssues = [...allIssues];
    }

    updateProjectCards();
}

// getDepartmentText는 issue-helpers.js에서 제공됨

function viewIssueDetail(issueId) {
    window.location.href = `/issues-management.html#issue-${issueId}`;
}

function refreshDashboard() {
    // 현재 선택된 프로젝트 기준으로 다시 로드
    const selectedProject = document.getElementById('projectFilter').value;
    if (selectedProject) {
        filterByProject();
    } else {
        initializeDashboard();
    }
}

// 로그인 처리
document.getElementById('loginForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    const username = document.getElementById('username').value;
    const password = document.getElementById('password').value;

    try {
        const user = await window.authManager.login(username, password);
        if (user) {
            document.getElementById('loginScreen').classList.add('hidden');
            await initializeDashboard();
        }
    } catch (error) {
        alert('로그인에 실패했습니다.');
    }
});

// 페이지 로드 시 초기화
document.addEventListener('DOMContentLoaded', () => {
    // AuthManager 로드 대기
    const checkAuthManager = () => {
        if (window.authManager) {
            initializeDashboard();
        } else {
            setTimeout(checkAuthManager, 100);
        }
    };
    checkAuthManager();
});

// ===== 두 번째 스크립트 블록 (API 로드 및 추가 기능) =====

function initializeDashboardApp() {
    console.log('API 스크립트 로드 완료 (issues-dashboard.html)');
}

// 완료 신청 관련 함수들
let selectedCompletionIssueId = null;
let completionPhotoBase64 = null;

function openCompletionRequestModal(issueId) {
    selectedCompletionIssueId = issueId;
    document.getElementById('completionRequestModal').classList.remove('hidden');

    // 폼 초기화
    document.getElementById('completionRequestForm').reset();
    document.getElementById('photoPreview').classList.add('hidden');
    document.getElementById('photoUploadArea').classList.remove('hidden');
    completionPhotoBase64 = null;
}

function closeCompletionRequestModal() {
    selectedCompletionIssueId = null;
    completionPhotoBase64 = null;
    document.getElementById('completionRequestModal').classList.add('hidden');
}

// 완료 신청 반려 관련 함수들
let selectedRejectionIssueId = null;

function openRejectionModal(issueId) {
    selectedRejectionIssueId = issueId;
    document.getElementById('rejectionModal').classList.remove('hidden');
    document.getElementById('rejectionReason').value = '';
    document.getElementById('rejectionReason').focus();
}

function closeRejectionModal() {
    selectedRejectionIssueId = null;
    document.getElementById('rejectionModal').classList.add('hidden');
}

async function submitRejection(event) {
    event.preventDefault();

    if (!selectedRejectionIssueId) {
        alert('이슈 ID가 없습니다.');
        return;
    }

    const rejectionReason = document.getElementById('rejectionReason').value.trim();
    if (!rejectionReason) {
        alert('반려 사유를 입력해주세요.');
        return;
    }

    try {
        const response = await fetch(`/api/issues/${selectedRejectionIssueId}/reject-completion`, {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                rejection_reason: rejectionReason
            })
        });

        if (response.ok) {
            alert('완료 신청이 반려되었습니다.');
            closeRejectionModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`반려 처리 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('반려 처리 오류:', error);
        alert('반려 처리 중 오류가 발생했습니다: ' + error.message);
    }
}

// 댓글 토글 기능
function toggleComments(issueId, opinionIndex) {
    const commentsDiv = document.getElementById(`comments-${issueId}-${opinionIndex}`);
    const chevron = document.getElementById(`comment-chevron-${issueId}-${opinionIndex}`);

    if (commentsDiv.classList.contains('hidden')) {
        commentsDiv.classList.remove('hidden');
        chevron.classList.add('fa-rotate-180');
    } else {
        commentsDiv.classList.add('hidden');
        chevron.classList.remove('fa-rotate-180');
    }
}

// 의견 제시 모달 관련
let selectedOpinionIssueId = null;

function openOpinionModal(issueId) {
    selectedOpinionIssueId = issueId;
    document.getElementById('opinionModal').classList.remove('hidden');
    document.getElementById('opinionText').value = '';
    document.getElementById('opinionText').focus();
}

function closeOpinionModal() {
    selectedOpinionIssueId = null;
    document.getElementById('opinionModal').classList.add('hidden');
}

// 댓글 추가 모달 관련
let selectedCommentIssueId = null;
let selectedCommentOpinionIndex = null;

function openCommentModal(issueId, opinionIndex) {
    selectedCommentIssueId = issueId;
    selectedCommentOpinionIndex = opinionIndex;
    document.getElementById('commentModal').classList.remove('hidden');
    document.getElementById('commentText').value = '';
    document.getElementById('commentText').focus();
}

function closeCommentModal() {
    selectedCommentIssueId = null;
    selectedCommentOpinionIndex = null;
    document.getElementById('commentModal').classList.add('hidden');
}

// 로그 기록 함수
async function logModification(issueId, action, details) {
    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`
            }
        });

        if (issueResponse.ok) {
            const issue = await issueResponse.json();
            const modificationLog = issue.modification_log || [];

            modificationLog.push({
                timestamp: new Date().toISOString(),
                user: currentUser.full_name || currentUser.username,
                user_id: currentUser.id,
                action: action,
                details: details
            });

            return modificationLog;
        }
    } catch (error) {
        console.error('로그 기록 오류:', error);
    }
    return null;
}

async function submitComment(event) {
    event.preventDefault();

    if (!selectedCommentIssueId || selectedCommentOpinionIndex === null) {
        alert('대상 의견이 선택되지 않았습니다.');
        return;
    }

    const commentText = document.getElementById('commentText').value.trim();
    if (!commentText) {
        alert('댓글을 입력해주세요.');
        return;
    }

    try {
        const issueResponse = await fetch(`/api/issues/${selectedCommentIssueId}`, {
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`
            }
        });

        if (!issueResponse.ok) {
            throw new Error('이슈 정보를 가져올 수 없습니다.');
        }

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];

        if (selectedCommentOpinionIndex >= opinions.length) {
            throw new Error('잘못된 의견 인덱스입니다.');
        }

        const now = new Date();
        const dateStr = now.toLocaleString('ko-KR', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit'
        });
        const newComment = `  └ [${currentUser.full_name || currentUser.username}] (${dateStr}): ${commentText}`;

        opinions[selectedCommentOpinionIndex] = opinions[selectedCommentOpinionIndex].trim() + '\n' + newComment;
        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${selectedCommentIssueId}/management`, {
            method: 'PUT',
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                solution: updatedSolution
            })
        });

        if (response.ok) {
            await logModification(selectedCommentIssueId, 'comment_added', {
                opinion_index: selectedCommentOpinionIndex,
                comment: commentText
            });
            alert('댓글이 추가되었습니다.');
            closeCommentModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`댓글 추가 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('댓글 추가 오류:', error);
        alert('댓글 추가 중 오류가 발생했습니다: ' + error.message);
    }
}

// 답글(대댓글) 관련
let selectedReplyIssueId = null;
let selectedReplyOpinionIndex = null;
let selectedReplyCommentIndex = null;

function openReplyModal(issueId, opinionIndex, commentIndex) {
    selectedReplyIssueId = issueId;
    selectedReplyOpinionIndex = opinionIndex;
    selectedReplyCommentIndex = commentIndex;
    document.getElementById('replyModal').classList.remove('hidden');
    document.getElementById('replyText').value = '';
    document.getElementById('replyText').focus();
}

function closeReplyModal() {
    selectedReplyIssueId = null;
    selectedReplyOpinionIndex = null;
    selectedReplyCommentIndex = null;
    document.getElementById('replyModal').classList.add('hidden');
}

async function submitReply(event) {
    event.preventDefault();

    if (!selectedReplyIssueId || selectedReplyOpinionIndex === null || selectedReplyCommentIndex === null) {
        alert('대상 댓글이 선택되지 않았습니다.');
        return;
    }

    const replyText = document.getElementById('replyText').value.trim();
    if (!replyText) {
        alert('답글을 입력해주세요.');
        return;
    }

    try {
        const issueResponse = await fetch(`/api/issues/${selectedReplyIssueId}`, {
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`
            }
        });

        if (!issueResponse.ok) {
            throw new Error('이슈 정보를 가져올 수 없습니다.');
        }

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];

        if (selectedReplyOpinionIndex >= opinions.length) {
            throw new Error('잘못된 의견 인덱스입니다.');
        }

        const now = new Date();
        const dateStr = now.toLocaleString('ko-KR', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit'
        });

        const lines = opinions[selectedReplyOpinionIndex].trim().split('\n');
        const newReply = `    ↳ [${currentUser.full_name || currentUser.username}] (${dateStr}): ${replyText}`;

        let commentCount = -1;
        let insertIndex = -1;

        for (let i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) {
                commentCount++;
                if (commentCount === selectedReplyCommentIndex) {
                    insertIndex = i + 1;
                    while (insertIndex < lines.length && lines[insertIndex].match(/^\s*↳/)) {
                        insertIndex++;
                    }
                    break;
                }
            }
        }

        if (insertIndex >= 0) {
            lines.splice(insertIndex, 0, newReply);
            opinions[selectedReplyOpinionIndex] = lines.join('\n');
        }

        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${selectedReplyIssueId}/management`, {
            method: 'PUT',
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                solution: updatedSolution
            })
        });

        if (response.ok) {
            await logModification(selectedReplyIssueId, 'reply_added', {
                opinion_index: selectedReplyOpinionIndex,
                comment_index: selectedReplyCommentIndex,
                reply: replyText
            });
            alert('답글이 추가되었습니다.');
            closeReplyModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`답글 추가 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('답글 추가 오류:', error);
        alert('답글 추가 중 오류가 발생했습니다: ' + error.message);
    }
}

// 의견 수정 관련
let selectedEditIssueId = null;
let selectedEditOpinionIndex = null;

async function editOpinion(issueId, opinionIndex) {
    selectedEditIssueId = issueId;
    selectedEditOpinionIndex = opinionIndex;

    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];

        if (opinionIndex >= opinions.length) throw new Error('잘못된 의견 인덱스입니다.');

        const opinion = opinions[opinionIndex].trim();
        const headerMatch = opinion.match(/^\[([^\]]+)\]\s*\(([^)]+)\)/);

        if (headerMatch) {
            const lines = opinion.substring(headerMatch[0].length).trim().split('\n');
            let mainContent = '';

            for (const line of lines) {
                if (!line.match(/^\s*[└├]/)) {
                    mainContent += (mainContent ? '\n' : '') + line;
                }
            }

            document.getElementById('editOpinionText').value = mainContent;
            document.getElementById('editOpinionModal').classList.remove('hidden');
            document.getElementById('editOpinionText').focus();
        }
    } catch (error) {
        console.error('의견 수정 준비 오류:', error);
        alert('의견을 불러오는 중 오류가 발생했습니다: ' + error.message);
    }
}

function closeEditOpinionModal() {
    selectedEditIssueId = null;
    selectedEditOpinionIndex = null;
    document.getElementById('editOpinionModal').classList.add('hidden');
}

async function submitEditOpinion(event) {
    event.preventDefault();

    if (!selectedEditIssueId || selectedEditOpinionIndex === null) {
        alert('대상 의견이 선택되지 않았습니다.');
        return;
    }

    const newText = document.getElementById('editOpinionText').value.trim();
    if (!newText) {
        alert('의견 내용을 입력해주세요.');
        return;
    }

    try {
        const issueResponse = await fetch(`/api/issues/${selectedEditIssueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];

        if (selectedEditOpinionIndex >= opinions.length) throw new Error('잘못된 의견 인덱스입니다.');

        const opinion = opinions[selectedEditOpinionIndex].trim();
        const headerMatch = opinion.match(/^\[([^\]]+)\]\s*\(([^)]+)\)/);

        if (headerMatch) {
            const lines = opinion.substring(headerMatch[0].length).trim().split('\n');
            let comments = [];

            for (const line of lines) {
                if (line.match(/^\s*[└├]/)) {
                    comments.push(line);
                }
            }

            opinions[selectedEditOpinionIndex] = headerMatch[0] + '\n' + newText +
                (comments.length > 0 ? '\n' + comments.join('\n') : '');
        }

        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${selectedEditIssueId}/management`, {
            method: 'PUT',
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ solution: updatedSolution })
        });

        if (response.ok) {
            alert('의견이 수정되었습니다.');
            closeEditOpinionModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`의견 수정 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('의견 수정 오류:', error);
        alert('의견 수정 중 오류가 발생했습니다: ' + error.message);
    }
}

// 의견 삭제
async function deleteOpinion(issueId, opinionIndex) {
    if (!confirm('이 의견을 삭제하시겠습니까? (댓글도 함께 삭제됩니다)')) return;

    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];

        if (opinionIndex >= opinions.length) throw new Error('잘못된 의견 인덱스입니다.');

        const deletedOpinion = opinions[opinionIndex];
        opinions.splice(opinionIndex, 1);

        const updatedSolution = opinions.length > 0 ? opinions.join('\n' + '─'.repeat(50) + '\n') : '';

        const response = await fetch(`/api/issues/${issueId}/management`, {
            method: 'PUT',
            headers: {
                'Authorization': `Bearer ${TokenManager.getToken()}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ solution: updatedSolution || null })
        });

        if (response.ok) {
            await logModification(issueId, 'opinion_deleted', { opinion_index: opinionIndex, deleted_content: deletedOpinion });
            alert('의견이 삭제되었습니다.');
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`의견 삭제 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('의견 삭제 오류:', error);
        alert('의견 삭제 중 오류가 발생했습니다: ' + error.message);
    }
}

// 댓글 수정
let selectedEditCommentIssueId = null;
let selectedEditCommentOpinionIndex = null;
let selectedEditCommentIndex = null;

async function editComment(issueId, opinionIndex, commentIndex) {
    selectedEditCommentIssueId = issueId;
    selectedEditCommentOpinionIndex = opinionIndex;
    selectedEditCommentIndex = commentIndex;

    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        const lines = opinions[opinionIndex].trim().split('\n');

        let commentCount = -1;
        for (const line of lines) {
            if (line.match(/^\s*└/)) {
                commentCount++;
                if (commentCount === commentIndex) {
                    const match = line.match(/└\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                    if (match) {
                        document.getElementById('editCommentText').value = match[3];
                        document.getElementById('editCommentModal').classList.remove('hidden');
                        document.getElementById('editCommentText').focus();
                    }
                    break;
                }
            }
        }
    } catch (error) {
        console.error('댓글 수정 준비 오류:', error);
        alert('댓글을 불러오는 중 오류가 발생했습니다: ' + error.message);
    }
}

function closeEditCommentModal() {
    selectedEditCommentIssueId = null;
    selectedEditCommentOpinionIndex = null;
    selectedEditCommentIndex = null;
    document.getElementById('editCommentModal').classList.add('hidden');
}

async function submitEditComment(event) {
    event.preventDefault();

    const newText = document.getElementById('editCommentText').value.trim();
    if (!newText) { alert('댓글 내용을 입력해주세요.'); return; }

    try {
        const issueResponse = await fetch(`/api/issues/${selectedEditCommentIssueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        const lines = opinions[selectedEditCommentOpinionIndex].trim().split('\n');

        let commentCount = -1;
        for (let i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) {
                commentCount++;
                if (commentCount === selectedEditCommentIndex) {
                    const match = lines[i].match(/└\s*\[([^\]]+)\]\s*\(([^)]+)\):/);
                    if (match) { lines[i] = `  └ [${match[1]}] (${match[2]}): ${newText}`; }
                    break;
                }
            }
        }

        opinions[selectedEditCommentOpinionIndex] = lines.join('\n');
        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${selectedEditCommentIssueId}/management`, {
            method: 'PUT',
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: updatedSolution })
        });

        if (response.ok) {
            await logModification(selectedEditCommentIssueId, 'comment_edited', { opinion_index: selectedEditCommentOpinionIndex, comment_index: selectedEditCommentIndex, new_content: newText });
            alert('댓글이 수정되었습니다.');
            closeEditCommentModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`댓글 수정 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('댓글 수정 오류:', error);
        alert('댓글 수정 중 오류가 발생했습니다: ' + error.message);
    }
}

// 댓글 삭제
async function deleteComment(issueId, opinionIndex, commentIndex) {
    if (!confirm('이 댓글을 삭제하시겠습니까? (답글도 함께 삭제됩니다)')) return;

    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        const lines = opinions[opinionIndex].trim().split('\n');

        let commentCount = -1;
        let deleteStart = -1;
        let deleteEnd = -1;

        for (let i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) {
                commentCount++;
                if (commentCount === commentIndex) {
                    deleteStart = i;
                    deleteEnd = i + 1;
                    while (deleteEnd < lines.length && lines[deleteEnd].match(/^\s*↳/)) { deleteEnd++; }
                    break;
                }
            }
        }

        if (deleteStart >= 0) {
            lines.splice(deleteStart, deleteEnd - deleteStart);
            opinions[opinionIndex] = lines.join('\n');
        }

        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${issueId}/management`, {
            method: 'PUT',
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: updatedSolution })
        });

        if (response.ok) {
            await logModification(issueId, 'comment_deleted', { opinion_index: opinionIndex, comment_index: commentIndex });
            alert('댓글이 삭제되었습니다.');
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`댓글 삭제 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('댓글 삭제 오류:', error);
        alert('댓글 삭제 중 오류가 발생했습니다: ' + error.message);
    }
}

// 대댓글(답글) 수정
let selectedEditReplyIssueId = null;
let selectedEditReplyOpinionIndex = null;
let selectedEditReplyCommentIndex = null;
let selectedEditReplyIndex = null;

async function editReply(issueId, opinionIndex, commentIndex, replyIndex) {
    selectedEditReplyIssueId = issueId;
    selectedEditReplyOpinionIndex = opinionIndex;
    selectedEditReplyCommentIndex = commentIndex;
    selectedEditReplyIndex = replyIndex;

    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        const lines = opinions[opinionIndex].trim().split('\n');

        let commentCount = -1;
        let replyCount = -1;

        for (const line of lines) {
            if (line.match(/^\s*└/)) { commentCount++; replyCount = -1; }
            else if (line.match(/^\s*↳/) && commentCount === commentIndex) {
                replyCount++;
                if (replyCount === replyIndex) {
                    const match = line.match(/↳\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                    if (match) {
                        document.getElementById('editReplyText').value = match[3];
                        document.getElementById('editReplyModal').classList.remove('hidden');
                        document.getElementById('editReplyText').focus();
                    }
                    break;
                }
            }
        }
    } catch (error) {
        console.error('답글 수정 준비 오류:', error);
        alert('답글을 불러오는 중 오류가 발생했습니다: ' + error.message);
    }
}

function closeEditReplyModal() {
    selectedEditReplyIssueId = null;
    selectedEditReplyOpinionIndex = null;
    selectedEditReplyCommentIndex = null;
    selectedEditReplyIndex = null;
    document.getElementById('editReplyModal').classList.add('hidden');
}

async function submitEditReply(event) {
    event.preventDefault();

    const newText = document.getElementById('editReplyText').value.trim();
    if (!newText) { alert('답글 내용을 입력해주세요.'); return; }

    try {
        const issueResponse = await fetch(`/api/issues/${selectedEditReplyIssueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        const lines = opinions[selectedEditReplyOpinionIndex].trim().split('\n');

        let commentCount = -1;
        let replyCount = -1;

        for (let i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) { commentCount++; replyCount = -1; }
            else if (lines[i].match(/^\s*↳/) && commentCount === selectedEditReplyCommentIndex) {
                replyCount++;
                if (replyCount === selectedEditReplyIndex) {
                    const match = lines[i].match(/↳\s*\[([^\]]+)\]\s*\(([^)]+)\):/);
                    if (match) { lines[i] = `    ↳ [${match[1]}] (${match[2]}): ${newText}`; }
                    break;
                }
            }
        }

        opinions[selectedEditReplyOpinionIndex] = lines.join('\n');
        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${selectedEditReplyIssueId}/management`, {
            method: 'PUT',
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: updatedSolution })
        });

        if (response.ok) {
            await logModification(selectedEditReplyIssueId, 'reply_edited', { opinion_index: selectedEditReplyOpinionIndex, comment_index: selectedEditReplyCommentIndex, reply_index: selectedEditReplyIndex, new_content: newText });
            alert('답글이 수정되었습니다.');
            closeEditReplyModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`답글 수정 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('답글 수정 오류:', error);
        alert('답글 수정 중 오류가 발생했습니다: ' + error.message);
    }
}

// 대댓글(답글) 삭제
async function deleteReply(issueId, opinionIndex, commentIndex, replyIndex) {
    if (!confirm('이 답글을 삭제하시겠습니까?')) return;

    try {
        const issueResponse = await fetch(`/api/issues/${issueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();
        const opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        const lines = opinions[opinionIndex].trim().split('\n');

        let commentCount = -1;
        let replyCount = -1;
        let deleteIndex = -1;

        for (let i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) { commentCount++; replyCount = -1; }
            else if (lines[i].match(/^\s*↳/) && commentCount === commentIndex) {
                replyCount++;
                if (replyCount === replyIndex) { deleteIndex = i; break; }
            }
        }

        if (deleteIndex >= 0) {
            lines.splice(deleteIndex, 1);
            opinions[opinionIndex] = lines.join('\n');
        }

        const updatedSolution = opinions.join('\n' + '─'.repeat(50) + '\n');

        const response = await fetch(`/api/issues/${issueId}/management`, {
            method: 'PUT',
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: updatedSolution })
        });

        if (response.ok) {
            await logModification(issueId, 'reply_deleted', { opinion_index: opinionIndex, comment_index: commentIndex, reply_index: replyIndex });
            alert('답글이 삭제되었습니다.');
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`답글 삭제 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('답글 삭제 오류:', error);
        alert('답글 삭제 중 오류가 발생했습니다: ' + error.message);
    }
}

async function submitOpinion(event) {
    event.preventDefault();

    if (!selectedOpinionIssueId) {
        alert('이슈 ID가 없습니다.');
        return;
    }

    const opinionText = document.getElementById('opinionText').value.trim();
    if (!opinionText) {
        alert('의견을 입력해주세요.');
        return;
    }

    try {
        const issueResponse = await fetch(`/api/issues/${selectedOpinionIssueId}`, {
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}` }
        });

        if (!issueResponse.ok) throw new Error('이슈 정보를 가져올 수 없습니다.');

        const issue = await issueResponse.json();

        const now = new Date();
        const dateStr = now.toLocaleString('ko-KR', {
            year: 'numeric', month: '2-digit', day: '2-digit',
            hour: '2-digit', minute: '2-digit'
        });
        const newOpinion = `[${currentUser.full_name || currentUser.username}] (${dateStr})\n${opinionText}`;

        const updatedSolution = issue.solution
            ? `${newOpinion}\n${'─'.repeat(50)}\n${issue.solution}`
            : newOpinion;

        const response = await fetch(`/api/issues/${selectedOpinionIssueId}/management`, {
            method: 'PUT',
            headers: { 'Authorization': `Bearer ${TokenManager.getToken()}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: updatedSolution })
        });

        if (response.ok) {
            alert('의견이 추가되었습니다.');
            closeOpinionModal();
            await initializeDashboard();
        } else {
            const error = await response.json();
            alert(`의견 추가 실패: ${error.detail || '알 수 없는 오류'}`);
        }
    } catch (error) {
        console.error('의견 추가 오류:', error);
        alert('의견 추가 중 오류가 발생했습니다: ' + error.message);
    }
}

function handleCompletionPhotoUpload(event) {
    const file = event.target.files[0];
    if (!file) return;

    if (file.size > 5 * 1024 * 1024) { alert('파일 크기는 5MB 이하여야 합니다.'); return; }
    if (!file.type.startsWith('image/')) { alert('이미지 파일만 업로드 가능합니다.'); return; }

    const reader = new FileReader();
    reader.onload = function(e) {
        completionPhotoBase64 = e.target.result;

        document.getElementById('previewImage').src = e.target.result;
        document.getElementById('photoUploadArea').classList.add('hidden');
        document.getElementById('photoPreview').classList.remove('hidden');
    };
    reader.readAsDataURL(file);
}

// 완료 신청 폼 제출 처리
document.addEventListener('DOMContentLoaded', function() {
    const completionForm = document.getElementById('completionRequestForm');
    if (completionForm) {
        completionForm.addEventListener('submit', async function(e) {
            e.preventDefault();

            if (!selectedCompletionIssueId) { alert('선택된 이슈가 없습니다.'); return; }
            if (!completionPhotoBase64) { alert('완료 사진을 업로드해주세요.'); return; }

            const comment = document.getElementById('completionComment').value.trim();

            try {
                const response = await fetch(`/api/issues/${selectedCompletionIssueId}/completion-request`, {
                    method: 'POST',
                    headers: { 'Authorization': `Bearer ${TokenManager.getToken()}`, 'Content-Type': 'application/json' },
                    body: JSON.stringify({ completion_photo: completionPhotoBase64, completion_comment: comment })
                });

                if (response.ok) {
                    alert('완료 신청이 성공적으로 제출되었습니다.');
                    closeCompletionRequestModal();
                    refreshDashboard();
                } else {
                    const error = await response.json();
                    alert(`완료 신청 실패: ${error.detail || '알 수 없는 오류'}`);
                }
            } catch (error) {
                console.error('완료 신청 오류:', error);
                alert('완료 신청 중 오류가 발생했습니다.');
            }
        });
    }
});

// 초기화
initializeDashboardApp();
