/**
 * m-dashboard.js — 현황판 모바일 페이지 로직
 */

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

// 모달/시트 상태
var selectedOpinionIssueId = null;
var selectedCommentIssueId = null;
var selectedCommentOpinionIndex = null;
var selectedReplyIssueId = null;
var selectedReplyOpinionIndex = null;
var selectedReplyCommentIndex = null;
var selectedCompletionIssueId = null;
var selectedRejectionIssueId = null;
var completionPhotoBase64 = null;

// 수정 상태
var editMode = null; // 'opinion', 'comment', 'reply'
var editIssueId = null;
var editOpinionIndex = null;
var editCommentIndex = null;
var editReplyIndex = null;

// ===== 초기화 =====
async function initialize() {
    currentUser = await mCheckAuth();
    if (!currentUser) return;

    await Promise.all([loadProjects(), loadIssues()]);
    updateStatistics();
    renderIssues();
    renderBottomNav('dashboard');
    hideLoading();
}

async function loadProjects() {
    try {
        var resp = await fetch(API_BASE_URL + '/projects/', {
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
        });
        if (resp.ok) {
            projects = await resp.json();
            var sel = document.getElementById('projectFilter');
            sel.innerHTML = '<option value="">전체 프로젝트</option>';
            projects.forEach(function (p) {
                sel.innerHTML += '<option value="' + p.id + '">' + escapeHtml(p.project_name) + '</option>';
            });
        }
    } catch (e) { console.error('프로젝트 로드 실패:', e); }
}

async function loadIssues() {
    try {
        var resp = await fetch(API_BASE_URL + '/issues/admin/all', {
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
        });
        if (resp.ok) {
            var data = await resp.json();
            allIssues = data.filter(function (i) { return i.review_status === 'in_progress'; });

            // 프로젝트별 순번 재할당
            allIssues.sort(function (a, b) { return new Date(a.reviewed_at) - new Date(b.reviewed_at); });
            var groups = {};
            allIssues.forEach(function (issue) {
                if (!groups[issue.project_id]) groups[issue.project_id] = [];
                groups[issue.project_id].push(issue);
            });
            Object.keys(groups).forEach(function (pid) {
                groups[pid].forEach(function (issue, idx) { issue.project_sequence_no = idx + 1; });
            });

            filteredIssues = allIssues.slice();
        }
    } catch (e) { console.error('이슈 로드 실패:', e); }
}

function updateStatistics() {
    var today = new Date().toDateString();
    var todayIssues = allIssues.filter(function (i) { return i.reviewed_at && new Date(i.reviewed_at).toDateString() === today; });
    var pending = allIssues.filter(function (i) { return i.completion_requested_at && i.review_status === 'in_progress'; });
    var overdue = allIssues.filter(function (i) { return i.expected_completion_date && new Date(i.expected_completion_date) < new Date(); });

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

function filterByProject() {
    var pid = document.getElementById('projectFilter').value;
    filteredIssues = pid ? allIssues.filter(function (i) { return i.project_id == pid; }) : allIssues.slice();
    renderIssues();
}

// ===== 이슈 상태 판별 =====
function getIssueStatus(issue) {
    if (issue.review_status === 'completed') return 'completed';
    if (issue.completion_requested_at) return 'pending_completion';
    if (issue.expected_completion_date) {
        var diff = (new Date(issue.expected_completion_date) - new Date()) / 86400000;
        if (diff < 0) return 'overdue';
        if (diff <= 3) return 'urgent';
    }
    return 'in_progress';
}

function getStatusBadgeHtml(status) {
    var map = {
        'in_progress': '<span class="m-badge in-progress"><i class="fas fa-cog"></i> 진행 중</span>',
        'urgent': '<span class="m-badge urgent"><i class="fas fa-exclamation-triangle"></i> 긴급</span>',
        'overdue': '<span class="m-badge overdue"><i class="fas fa-clock"></i> 지연됨</span>',
        'pending_completion': '<span class="m-badge pending-completion"><i class="fas fa-hourglass-half"></i> 완료 대기</span>',
        'completed': '<span class="m-badge completed"><i class="fas fa-check-circle"></i> 완료됨</span>'
    };
    return map[status] || map['in_progress'];
}

// ===== 렌더링 =====
function renderIssues() {
    var container = document.getElementById('issuesList');
    var empty = document.getElementById('emptyState');

    if (!filteredIssues.length) {
        container.innerHTML = '';
        empty.classList.remove('hidden');
        return;
    }
    empty.classList.add('hidden');

    // 날짜별 그룹화 (reviewed_at 기준)
    var grouped = {};
    var dateObjs = {};
    filteredIssues.forEach(function (issue) {
        var d = new Date(issue.reviewed_at || issue.report_date);
        var key = d.toLocaleDateString('ko-KR');
        if (!grouped[key]) { grouped[key] = []; dateObjs[key] = d; }
        grouped[key].push(issue);
    });

    var html = Object.keys(grouped)
        .sort(function (a, b) { return dateObjs[b] - dateObjs[a]; })
        .map(function (dateKey) {
            var issues = grouped[dateKey];
            return '<div class="m-date-group"><div class="m-date-header">' +
                '<i class="fas fa-calendar-alt"></i>' +
                '<span>' + dateKey + '</span>' +
                '<span class="m-date-count">(' + issues.length + '건)</span></div>' +
                issues.map(function (issue) { return renderIssueCard(issue); }).join('') +
                '</div>';
        }).join('');

    container.innerHTML = html;
}

function renderIssueCard(issue) {
    var project = projects.find(function (p) { return p.id === issue.project_id; });
    var projectName = project ? project.project_name : '미지정';
    var status = getIssueStatus(issue);
    var photos = getPhotoPaths(issue);
    var isPending = status === 'pending_completion';

    // 의견/댓글 파싱
    var opinionsHtml = renderOpinions(issue);

    // 완료 반려 내용
    var rejectionHtml = '';
    if (issue.completion_rejection_reason) {
        var rejAt = issue.completion_rejected_at ? formatKSTDateTime(issue.completion_rejected_at) : '';
        rejectionHtml = '<div style="background:#fff7ed;border-left:3px solid #f97316;border-radius:8px;padding:8px 10px;margin-top:8px;font-size:12px;">' +
            '<div style="font-weight:600;color:#c2410c;margin-bottom:2px"><i class="fas fa-exclamation-triangle" style="margin-right:4px"></i>완료 반려</div>' +
            '<div style="color:#9a3412">' + (rejAt ? '[' + rejAt + '] ' : '') + escapeHtml(issue.completion_rejection_reason) + '</div></div>';
    }

    // 완료 대기 정보
    var completionInfoHtml = '';
    if (isPending) {
        var cPhotos = getCompletionPhotoPaths(issue);
        completionInfoHtml = '<div class="m-completion-info">' +
            '<div style="font-size:12px;font-weight:600;color:#6d28d9;margin-bottom:6px"><i class="fas fa-check-circle" style="margin-right:4px"></i>완료 신청 정보</div>' +
            (cPhotos.length ? renderPhotoThumbs(cPhotos) : '<div style="font-size:12px;color:#9ca3af">완료 사진 없음</div>') +
            '<div style="font-size:12px;color:#6b7280;margin-top:4px">' + (issue.completion_comment || '코멘트 없음') + '</div>' +
            '<div style="font-size:11px;color:#9ca3af;margin-top:4px">신청: ' + formatKSTDateTime(issue.completion_requested_at) + '</div>' +
            '</div>';
    }

    // 액션 버튼
    var actionHtml = '';
    if (isPending) {
        actionHtml = '<div class="m-action-row">' +
            '<button class="m-action-btn red" onclick="openRejectionSheet(' + issue.id + ')"><i class="fas fa-times"></i>반려</button>' +
            '<button class="m-action-btn green" onclick="event.stopPropagation();openOpinionSheet(' + issue.id + ')"><i class="fas fa-comment-medical"></i>의견</button>' +
            '</div>';
    } else {
        actionHtml = '<div class="m-action-row">' +
            '<button class="m-action-btn green" onclick="openCompletionSheet(' + issue.id + ')"><i class="fas fa-check"></i>완료신청</button>' +
            '<button class="m-action-btn blue" onclick="event.stopPropagation();openOpinionSheet(' + issue.id + ')"><i class="fas fa-comment-medical"></i>의견</button>' +
            '</div>';
    }

    return '<div class="m-card border-blue">' +
        '<div class="m-card-header">' +
            '<div><span class="m-card-no">No.' + (issue.project_sequence_no || '-') + '</span>' +
            '<span class="m-card-project">' + escapeHtml(projectName) + '</span></div>' +
            getStatusBadgeHtml(status) +
        '</div>' +
        '<div class="m-card-title">' + escapeHtml(getIssueTitle(issue)) + '</div>' +
        '<div class="m-card-body">' +
            // 상세 내용
            '<div style="font-size:13px;color:#6b7280;line-height:1.5;margin-bottom:8px" class="text-ellipsis-3">' + escapeHtml(getIssueDetail(issue)) + '</div>' +
            // 정보행
            '<div style="display:flex;gap:12px;font-size:12px;color:#9ca3af;margin-bottom:8px">' +
                '<span><i class="fas fa-user" style="margin-right:3px"></i>' + escapeHtml(issue.reporter?.full_name || issue.reporter?.username || '-') + '</span>' +
                '<span><i class="fas fa-tag" style="margin-right:3px"></i>' + getCategoryText(issue.category || issue.final_category) + '</span>' +
                (issue.expected_completion_date ? '<span><i class="fas fa-calendar-alt" style="margin-right:3px"></i>' + formatKSTDate(issue.expected_completion_date) + '</span>' : '') +
            '</div>' +
            // 사진
            (photos.length ? renderPhotoThumbs(photos) : '') +
            // 해결방안 / 의견 섹션
            '<div style="margin-top:8px">' +
                renderManagementComment(issue) +
                opinionsHtml +
            '</div>' +
            rejectionHtml +
            completionInfoHtml +
        '</div>' +
        actionHtml +
        '<div class="m-card-footer">' +
            '<span>' + getTimeAgo(issue.report_date) + '</span>' +
            '<span>ID: ' + issue.id + '</span>' +
        '</div>' +
    '</div>';
}

// ===== 관리 코멘트 (확정 해결방안) =====
function renderManagementComment(issue) {
    var raw = issue.management_comment || issue.final_description || '';
    raw = raw.replace(/\[완료 반려[^\]]*\][^\n]*/g, '').trim();
    var defaults = ['중복작업 신고용', '상세 내용 없음', '자재 누락', '설계 오류', '반입 불량', '검사 누락', '기타', '부적합명', '상세내용', '상세 내용'];
    var lines = raw.split('\n').filter(function (l) { var t = l.trim(); return t && defaults.indexOf(t) < 0; });
    var content = lines.join('\n').trim();

    return '<div style="background:#fef2f2;border-left:3px solid #fca5a5;border-radius:8px;padding:8px 10px;margin-bottom:6px">' +
        '<div style="font-size:' + (content ? '12' : '12') + 'px;color:' + (content ? '#991b1b' : '#d1d5db') + ';line-height:1.5;white-space:pre-wrap">' +
        (content ? escapeHtml(content) : '확정된 해결 방안 없음') +
        '</div></div>';
}

// ===== 의견/댓글/답글 렌더링 =====
function renderOpinions(issue) {
    if (!issue.solution || !issue.solution.trim()) {
        return '';
    }

    var opinions = issue.solution.split(/─{30,}/);
    var validOpinions = opinions.filter(function (o) { return o.trim(); });
    if (!validOpinions.length) return '';

    var toggleId = 'opinions-' + issue.id;
    var html = '<button class="m-opinions-toggle" onclick="toggleOpinions(\'' + toggleId + '\')">' +
        '<i class="fas fa-comments"></i> 의견 ' + validOpinions.length + '개' +
        '<i class="fas fa-chevron-down" style="font-size:10px;transition:transform 0.2s" id="chevron-' + toggleId + '"></i></button>' +
        '<div id="' + toggleId + '" class="hidden" style="margin-top:6px">';

    validOpinions.forEach(function (opinion, opinionIndex) {
        var trimmed = opinion.trim();
        var headerMatch = trimmed.match(/^\[([^\]]+)\]\s*\(([^)]+)\)/);

        if (headerMatch) {
            var author = headerMatch[1];
            var datetime = headerMatch[2];
            var rest = trimmed.substring(headerMatch[0].length).trim().split('\n');
            var mainContent = '';
            var comments = [];
            var currentCommentIdx = -1;

            rest.forEach(function (line) {
                if (line.match(/^\s*└/)) {
                    var cm = line.match(/└\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                    if (cm) { comments.push({ author: cm[1], datetime: cm[2], content: cm[3], replies: [] }); currentCommentIdx = comments.length - 1; }
                } else if (line.match(/^\s*↳/)) {
                    var rm = line.match(/↳\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                    if (rm && currentCommentIdx >= 0) { comments[currentCommentIdx].replies.push({ author: rm[1], datetime: rm[2], content: rm[3] }); }
                } else {
                    mainContent += (mainContent ? '\n' : '') + line;
                }
            });

            var isOwn = currentUser && (author === currentUser.full_name || author === currentUser.username);

            html += '<div class="m-opinion-card">' +
                '<div class="m-opinion-header">' +
                    '<div class="m-opinion-avatar">' + author.charAt(0) + '</div>' +
                    '<span class="m-opinion-author">' + escapeHtml(author) + '</span>' +
                    '<span class="m-opinion-time">' + escapeHtml(datetime) + '</span>' +
                '</div>' +
                '<div class="m-opinion-text">' + escapeHtml(mainContent) + '</div>' +
                '<div class="m-opinion-actions">' +
                    '<button class="m-opinion-action-btn comment-btn" onclick="openCommentSheet(' + issue.id + ',' + opinionIndex + ')"><i class="fas fa-comment"></i>댓글</button>' +
                    (isOwn ? '<button class="m-opinion-action-btn edit-btn" onclick="openEditSheet(\'opinion\',' + issue.id + ',' + opinionIndex + ')"><i class="fas fa-edit"></i>수정</button>' +
                        '<button class="m-opinion-action-btn delete-btn" onclick="deleteOpinion(' + issue.id + ',' + opinionIndex + ')"><i class="fas fa-trash"></i>삭제</button>' : '') +
                '</div>';

            // 댓글
            comments.forEach(function (comment, commentIndex) {
                var isOwnComment = currentUser && (comment.author === currentUser.full_name || comment.author === currentUser.username);
                html += '<div class="m-comment">' +
                    '<div class="m-comment-header">' +
                        '<div class="m-comment-avatar">' + comment.author.charAt(0) + '</div>' +
                        '<span style="font-weight:600;color:#111827;font-size:11px">' + escapeHtml(comment.author) + '</span>' +
                        '<span style="color:#9ca3af;font-size:10px">' + escapeHtml(comment.datetime) + '</span>' +
                    '</div>' +
                    '<div class="m-comment-text">' + escapeHtml(comment.content) + '</div>' +
                    '<div style="display:flex;gap:4px;margin-top:4px;padding-left:22px">' +
                        '<button class="m-opinion-action-btn reply-btn" onclick="openReplySheet(' + issue.id + ',' + opinionIndex + ',' + commentIndex + ')"><i class="fas fa-reply"></i>답글</button>' +
                        (isOwnComment ? '<button class="m-opinion-action-btn edit-btn" onclick="openEditSheet(\'comment\',' + issue.id + ',' + opinionIndex + ',' + commentIndex + ')"><i class="fas fa-edit"></i></button>' +
                            '<button class="m-opinion-action-btn delete-btn" onclick="deleteComment(' + issue.id + ',' + opinionIndex + ',' + commentIndex + ')"><i class="fas fa-trash"></i></button>' : '') +
                    '</div>';

                // 답글
                comment.replies.forEach(function (reply, replyIndex) {
                    var isOwnReply = currentUser && (reply.author === currentUser.full_name || reply.author === currentUser.username);
                    html += '<div class="m-reply">' +
                        '<div class="m-reply-header">' +
                            '<i class="fas fa-reply" style="color:#93c5fd;font-size:9px;margin-right:3px"></i>' +
                            '<span style="font-weight:600;color:#111827;font-size:10px">' + escapeHtml(reply.author) + '</span>' +
                            '<span style="color:#9ca3af;font-size:9px;margin-left:3px">' + escapeHtml(reply.datetime) + '</span>' +
                            (isOwnReply ? '<button class="m-opinion-action-btn edit-btn" style="margin-left:auto;padding:1px 4px" onclick="openEditSheet(\'reply\',' + issue.id + ',' + opinionIndex + ',' + commentIndex + ',' + replyIndex + ')"><i class="fas fa-edit" style="font-size:9px"></i></button>' +
                                '<button class="m-opinion-action-btn delete-btn" style="padding:1px 4px" onclick="deleteReply(' + issue.id + ',' + opinionIndex + ',' + commentIndex + ',' + replyIndex + ')"><i class="fas fa-trash" style="font-size:9px"></i></button>' : '') +
                        '</div>' +
                        '<div class="m-reply-text">' + escapeHtml(reply.content) + '</div>' +
                    '</div>';
                });

                html += '</div>'; // m-comment
            });

            html += '</div>'; // m-opinion-card
        }
    });

    html += '</div>';
    return html;
}

function toggleOpinions(id) {
    var el = document.getElementById(id);
    var chevron = document.getElementById('chevron-' + id);
    if (el.classList.contains('hidden')) {
        el.classList.remove('hidden');
        if (chevron) chevron.style.transform = 'rotate(180deg)';
    } else {
        el.classList.add('hidden');
        if (chevron) chevron.style.transform = '';
    }
}

// ===== 의견 제시 =====
function openOpinionSheet(issueId) {
    selectedOpinionIssueId = issueId;
    document.getElementById('opinionText').value = '';
    openSheet('opinion');
}

async function submitOpinion() {
    if (!selectedOpinionIssueId) return;
    var text = document.getElementById('opinionText').value.trim();
    if (!text) { showToast('의견을 입력해주세요.', 'warning'); return; }

    try {
        var issueResp = await fetch(API_BASE_URL + '/issues/' + selectedOpinionIssueId, {
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
        });
        if (!issueResp.ok) throw new Error('이슈 조회 실패');
        var issue = await issueResp.json();

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

        var solution = issue.solution ? newOpinion + '\n' + '─'.repeat(50) + '\n' + issue.solution : newOpinion;

        var resp = await fetch(API_BASE_URL + '/issues/' + selectedOpinionIssueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: solution })
        });

        if (resp.ok) {
            showToast('의견이 추가되었습니다.', 'success');
            closeSheet('opinion');
            await refreshData();
        } else { throw new Error('저장 실패'); }
    } catch (e) {
        console.error('의견 제시 오류:', e);
        showToast('오류: ' + e.message, 'error');
    }
}

// ===== 댓글 추가 =====
function openCommentSheet(issueId, opinionIndex) {
    selectedCommentIssueId = issueId;
    selectedCommentOpinionIndex = opinionIndex;
    document.getElementById('commentText').value = '';
    openSheet('comment');
}

async function submitComment() {
    if (!selectedCommentIssueId || selectedCommentOpinionIndex === null) return;
    var text = document.getElementById('commentText').value.trim();
    if (!text) { showToast('댓글을 입력해주세요.', 'warning'); return; }

    try {
        var issue = await (await fetch(API_BASE_URL + '/issues/' + selectedCommentIssueId, {
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
        })).json();

        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        if (selectedCommentOpinionIndex >= opinions.length) throw new Error('잘못된 인덱스');

        var dateStr = new Date().toLocaleString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
        opinions[selectedCommentOpinionIndex] = opinions[selectedCommentOpinionIndex].trim() + '\n  └ [' + (currentUser.full_name || currentUser.username) + '] (' + dateStr + '): ' + text;

        var resp = await fetch(API_BASE_URL + '/issues/' + selectedCommentIssueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: opinions.join('\n' + '─'.repeat(50) + '\n') })
        });

        if (resp.ok) { showToast('댓글이 추가되었습니다.', 'success'); closeSheet('comment'); await refreshData(); }
        else throw new Error('저장 실패');
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

// ===== 답글 추가 =====
function openReplySheet(issueId, opinionIndex, commentIndex) {
    selectedReplyIssueId = issueId;
    selectedReplyOpinionIndex = opinionIndex;
    selectedReplyCommentIndex = commentIndex;
    document.getElementById('replyText').value = '';
    openSheet('reply');
}

async function submitReply() {
    if (!selectedReplyIssueId || selectedReplyOpinionIndex === null || selectedReplyCommentIndex === null) return;
    var text = document.getElementById('replyText').value.trim();
    if (!text) { showToast('답글을 입력해주세요.', 'warning'); return; }

    try {
        var issue = await (await fetch(API_BASE_URL + '/issues/' + selectedReplyIssueId, {
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
        })).json();

        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        var lines = opinions[selectedReplyOpinionIndex].trim().split('\n');
        var dateStr = new Date().toLocaleString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
        var newReply = '    ↳ [' + (currentUser.full_name || currentUser.username) + '] (' + dateStr + '): ' + text;

        var commentCount = -1;
        var insertIndex = -1;
        for (var 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');

        var resp = await fetch(API_BASE_URL + '/issues/' + selectedReplyIssueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: opinions.join('\n' + '─'.repeat(50) + '\n') })
        });

        if (resp.ok) { showToast('답글이 추가되었습니다.', 'success'); closeSheet('reply'); await refreshData(); }
        else throw new Error('저장 실패');
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

// ===== 수정 =====
function openEditSheet(mode, issueId, opinionIndex, commentIndex, replyIndex) {
    editMode = mode;
    editIssueId = issueId;
    editOpinionIndex = opinionIndex;
    editCommentIndex = commentIndex !== undefined ? commentIndex : null;
    editReplyIndex = replyIndex !== undefined ? replyIndex : null;

    var titles = { opinion: '의견 수정', comment: '댓글 수정', reply: '답글 수정' };
    document.getElementById('editSheetTitle').innerHTML = '<i class="fas fa-edit" style="color:#22c55e;margin-right:6px"></i>' + titles[mode];

    // 현재 내용 로드
    fetch(API_BASE_URL + '/issues/' + issueId, {
        headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
    }).then(function (r) { return r.json(); }).then(function (issue) {
        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        var opinion = opinions[opinionIndex] || '';

        if (mode === 'opinion') {
            var hm = opinion.trim().match(/^\[([^\]]+)\]\s*\(([^)]+)\)/);
            if (hm) {
                var restLines = opinion.trim().substring(hm[0].length).trim().split('\n');
                var main = restLines.filter(function (l) { return !l.match(/^\s*[└↳]/); }).join('\n');
                document.getElementById('editText').value = main;
            }
        } else if (mode === 'comment') {
            var cLines = opinion.trim().split('\n');
            var cc = -1;
            for (var i = 0; i < cLines.length; i++) {
                if (cLines[i].match(/^\s*└/)) {
                    cc++;
                    if (cc === commentIndex) {
                        var m = cLines[i].match(/└\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                        if (m) document.getElementById('editText').value = m[3];
                        break;
                    }
                }
            }
        } else if (mode === 'reply') {
            var rLines = opinion.trim().split('\n');
            var rc = -1;
            var ri = -1;
            for (var j = 0; j < rLines.length; j++) {
                if (rLines[j].match(/^\s*└/)) { rc++; ri = -1; }
                else if (rLines[j].match(/^\s*↳/)) {
                    ri++;
                    if (rc === commentIndex && ri === replyIndex) {
                        var rm = rLines[j].match(/↳\s*\[([^\]]+)\]\s*\(([^)]+)\):\s*(.+)/);
                        if (rm) document.getElementById('editText').value = rm[3];
                        break;
                    }
                }
            }
        }
        openSheet('edit');
    });
}

async function submitEdit() {
    var newText = document.getElementById('editText').value.trim();
    if (!newText) { showToast('내용을 입력해주세요.', 'warning'); return; }

    try {
        var issue = await (await fetch(API_BASE_URL + '/issues/' + editIssueId, {
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() }
        })).json();

        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        var lines = opinions[editOpinionIndex].trim().split('\n');

        if (editMode === 'opinion') {
            var hm = opinions[editOpinionIndex].trim().match(/^\[([^\]]+)\]\s*\(([^)]+)\)/);
            if (hm) {
                var commentLines = lines.filter(function (l) { return l.match(/^\s*[└↳]/); });
                opinions[editOpinionIndex] = hm[0] + '\n' + newText + (commentLines.length ? '\n' + commentLines.join('\n') : '');
            }
        } else if (editMode === 'comment') {
            var cc = -1;
            for (var i = 0; i < lines.length; i++) {
                if (lines[i].match(/^\s*└/)) {
                    cc++;
                    if (cc === editCommentIndex) {
                        var m = lines[i].match(/└\s*\[([^\]]+)\]\s*\(([^)]+)\):/);
                        if (m) lines[i] = '  └ [' + m[1] + '] (' + m[2] + '): ' + newText;
                        break;
                    }
                }
            }
            opinions[editOpinionIndex] = lines.join('\n');
        } else if (editMode === 'reply') {
            var rc = -1, ri = -1;
            for (var j = 0; j < lines.length; j++) {
                if (lines[j].match(/^\s*└/)) { rc++; ri = -1; }
                else if (lines[j].match(/^\s*↳/)) {
                    ri++;
                    if (rc === editCommentIndex && ri === editReplyIndex) {
                        var rm = lines[j].match(/↳\s*\[([^\]]+)\]\s*\(([^)]+)\):/);
                        if (rm) lines[j] = '    ↳ [' + rm[1] + '] (' + rm[2] + '): ' + newText;
                        break;
                    }
                }
            }
            opinions[editOpinionIndex] = lines.join('\n');
        }

        var resp = await fetch(API_BASE_URL + '/issues/' + editIssueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: opinions.join('\n' + '─'.repeat(50) + '\n') })
        });

        if (resp.ok) { showToast('수정되었습니다.', 'success'); closeSheet('edit'); await refreshData(); }
        else throw new Error('저장 실패');
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

// ===== 삭제 =====
async function deleteOpinion(issueId, opinionIndex) {
    if (!confirm('이 의견을 삭제하시겠습니까?')) return;
    try {
        var issue = await (await fetch(API_BASE_URL + '/issues/' + issueId, { headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() } })).json();
        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        opinions.splice(opinionIndex, 1);
        await fetch(API_BASE_URL + '/issues/' + issueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: opinions.length ? opinions.join('\n' + '─'.repeat(50) + '\n') : null })
        });
        showToast('의견이 삭제되었습니다.', 'success');
        await refreshData();
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

async function deleteComment(issueId, opinionIndex, commentIndex) {
    if (!confirm('이 댓글을 삭제하시겠습니까?')) return;
    try {
        var issue = await (await fetch(API_BASE_URL + '/issues/' + issueId, { headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() } })).json();
        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        var lines = opinions[opinionIndex].trim().split('\n');
        var cc = -1, start = -1, end = -1;
        for (var i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) { cc++; if (cc === commentIndex) { start = i; end = i + 1; while (end < lines.length && lines[end].match(/^\s*↳/)) end++; break; } }
        }
        if (start >= 0) { lines.splice(start, end - start); opinions[opinionIndex] = lines.join('\n'); }
        await fetch(API_BASE_URL + '/issues/' + issueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: opinions.join('\n' + '─'.repeat(50) + '\n') })
        });
        showToast('댓글이 삭제되었습니다.', 'success');
        await refreshData();
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

async function deleteReply(issueId, opinionIndex, commentIndex, replyIndex) {
    if (!confirm('이 답글을 삭제하시겠습니까?')) return;
    try {
        var issue = await (await fetch(API_BASE_URL + '/issues/' + issueId, { headers: { 'Authorization': 'Bearer ' + TokenManager.getToken() } })).json();
        var opinions = issue.solution ? issue.solution.split(/─{30,}/) : [];
        var lines = opinions[opinionIndex].trim().split('\n');
        var cc = -1, ri = -1;
        for (var i = 0; i < lines.length; i++) {
            if (lines[i].match(/^\s*└/)) { cc++; ri = -1; }
            else if (lines[i].match(/^\s*↳/)) { ri++; if (cc === commentIndex && ri === replyIndex) { lines.splice(i, 1); break; } }
        }
        opinions[opinionIndex] = lines.join('\n');
        await fetch(API_BASE_URL + '/issues/' + issueId + '/management', {
            method: 'PUT',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ solution: opinions.join('\n' + '─'.repeat(50) + '\n') })
        });
        showToast('답글이 삭제되었습니다.', 'success');
        await refreshData();
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

// ===== 완료 신청 =====
function openCompletionSheet(issueId) {
    selectedCompletionIssueId = issueId;
    completionPhotoBase64 = null;
    document.getElementById('completionPhotoInput').value = '';
    document.getElementById('completionPhotoPreview').classList.add('hidden');
    document.getElementById('completionComment').value = '';
    openSheet('completion');
}

function handleCompletionPhoto(event) {
    var file = event.target.files[0];
    if (!file) return;
    if (file.size > 5 * 1024 * 1024) { showToast('파일 크기는 5MB 이하여야 합니다.', 'warning'); event.target.value = ''; return; }
    if (!file.type.startsWith('image/')) { showToast('이미지 파일만 가능합니다.', 'warning'); event.target.value = ''; return; }
    var reader = new FileReader();
    reader.onload = function (e) {
        completionPhotoBase64 = e.target.result.split(',')[1];
        var preview = document.getElementById('completionPhotoPreview');
        preview.src = e.target.result;
        preview.classList.remove('hidden');
    };
    reader.readAsDataURL(file);
}

async function submitCompletionRequest() {
    if (!selectedCompletionIssueId) return;
    if (!completionPhotoBase64) { showToast('완료 사진을 업로드해주세요.', 'warning'); return; }

    try {
        var body = { completion_photo: completionPhotoBase64 };
        var comment = document.getElementById('completionComment').value.trim();
        if (comment) body.completion_comment = comment;

        var resp = await fetch(API_BASE_URL + '/issues/' + selectedCompletionIssueId + '/request-completion', {
            method: 'POST',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify(body)
        });

        if (resp.ok) {
            showToast('완료 신청이 접수되었습니다.', 'success');
            closeSheet('completion');
            await refreshData();
        } else {
            var err = await resp.json();
            throw new Error(err.detail || '완료 신청 실패');
        }
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

// ===== 완료 반려 =====
function openRejectionSheet(issueId) {
    selectedRejectionIssueId = issueId;
    document.getElementById('rejectionReason').value = '';
    openSheet('rejection');
}

async function submitRejection() {
    if (!selectedRejectionIssueId) return;
    var reason = document.getElementById('rejectionReason').value.trim();
    if (!reason) { showToast('반려 사유를 입력해주세요.', 'warning'); return; }

    try {
        var resp = await fetch(API_BASE_URL + '/issues/' + selectedRejectionIssueId + '/reject-completion', {
            method: 'POST',
            headers: { 'Authorization': 'Bearer ' + TokenManager.getToken(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ rejection_reason: reason })
        });

        if (resp.ok) {
            showToast('완료 신청이 반려되었습니다.', 'success');
            closeSheet('rejection');
            await refreshData();
        } else {
            var err = await resp.json();
            throw new Error(err.detail || '반려 실패');
        }
    } catch (e) { showToast('오류: ' + e.message, 'error'); }
}

// ===== 새로고침 =====
async function refreshData() {
    await loadIssues();
    filterByProject();
    updateStatistics();
}

function refreshPage() {
    location.reload();
}

// ===== 시작 =====
document.addEventListener('DOMContentLoaded', initialize);
