/**
 * chat-report.js — 챗봇 기반 신고 접수 상태머신 + 대화 로직
 */

// ── 상태 정의 ──
const STATE = {
    INIT: 'INIT',
    PHOTO_TEXT: 'PHOTO_TEXT',
    CLASSIFY_TYPE: 'CLASSIFY_TYPE',
    CLASSIFY_CATEGORY: 'CLASSIFY_CATEGORY',
    CLASSIFY_ITEM: 'CLASSIFY_ITEM',
    LOCATION: 'LOCATION',
    PROJECT: 'PROJECT',
    CONFIRM: 'CONFIRM',
    SUBMIT: 'SUBMIT',
};

let currentState = STATE.INIT;

// ── 신고 데이터 ──
let reportData = {
    photos: [],
    description: '',
    organized_description: '',
    issue_type: null,        // 'nonconformity' | 'facility' | 'safety'
    issue_category_id: null,
    issue_category_name: null,
    issue_item_id: null,
    issue_item_name: null,
    custom_item_name: null,
    factory_category_id: null,
    factory_name: null,
    workplace_id: null,
    workplace_name: null,
    custom_location: null,
    project_id: null,
    project_name: null,
    tbm_session_id: null,
};

// ── 참조 데이터 ──
let refData = {
    factories: [],
    workplaces: {},   // { factory_id: [workplaces] }
    projects: [],
    tbmSessions: [],
    categories: {},   // { nonconformity: [...], facility: [...], safety: [...] }
    items: {},        // { category_id: [...] }
};

// ── AI 분석 결과 캐시 ──
let aiAnalysis = null;

// ── DOM ──
const API_BASE = window.API_BASE_URL || 'http://localhost:30105/api';
const AI_API_BASE = (() => {
    const hostname = window.location.hostname;
    const protocol = window.location.protocol;
    if (hostname.includes('technicalkorea.net')) {
        return protocol + '//' + hostname + '/ai-api';
    }
    return protocol + '//' + hostname + ':30200/api/ai';
})();

let chatArea, textInput, sendBtn, photoInput, photoBtn;

// ── 초기화 ──
document.addEventListener('DOMContentLoaded', () => {
    chatArea = document.getElementById('chatArea');
    textInput = document.getElementById('textInput');
    sendBtn = document.getElementById('sendBtn');
    photoInput = document.getElementById('chatPhotoInput');
    photoBtn = document.getElementById('photoBtn');

    sendBtn.addEventListener('click', onSend);
    textInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); onSend(); }
    });
    textInput.addEventListener('input', () => {
        textInput.style.height = 'auto';
        textInput.style.height = Math.min(textInput.scrollHeight, 100) + 'px';
        sendBtn.disabled = !textInput.value.trim() && reportData.photos.length === 0;
    });
    photoBtn.addEventListener('click', () => photoInput.click());
    photoInput.addEventListener('change', onPhotoSelect);

    initChat();
});

// ── initChat: 인사 + 데이터 프리패치 ──
async function initChat() {
    appendBot('안녕하세요! AI 신고 도우미입니다.\n\n현장에서 발견한 문제를 **사진과 함께 설명**해주시면, 신고 접수를 도와드리겠습니다.\n\n📎 버튼으로 사진을 첨부하고, 어떤 문제인지 간단히 입력해주세요.');

    // 데이터 프리패치
    try {
        const today = new Date().toISOString().slice(0, 10);
        const headers = getHeaders();

        const [factoriesRes, projectsRes, tbmRes] = await Promise.all([
            fetch(`${API_BASE}/workplaces/categories/active/list`, { headers }),
            fetch(`${API_BASE}/projects/active/list`, { headers }),
            fetch(`${API_BASE}/tbm/sessions/date/${today}`, { headers }),
        ]);

        if (factoriesRes.ok) {
            const d = await factoriesRes.json();
            refData.factories = d.data || [];
        }
        if (projectsRes.ok) {
            const d = await projectsRes.json();
            refData.projects = d.data || [];
        }
        if (tbmRes.ok) {
            const d = await tbmRes.json();
            refData.tbmSessions = d.data || [];
        }

        // 카테고리 3가지 유형 동시 로드
        const types = ['nonconformity', 'facility', 'safety'];
        const catResults = await Promise.all(
            types.map(t => fetch(`${API_BASE}/work-issues/categories/type/${t}`, { headers }).then(r => r.ok ? r.json() : { data: [] }))
        );
        types.forEach((t, i) => {
            refData.categories[t] = catResults[i].data || [];
        });

    } catch (err) {
        console.error('데이터 프리패치 실패:', err);
    }

    currentState = STATE.PHOTO_TEXT;
    updateInputBar();
}

// ── 전송 핸들러 ──
function onSend() {
    const text = textInput.value.trim();
    if (!text && reportData.photos.length === 0) return;

    if (currentState === STATE.PHOTO_TEXT) {
        handlePhotoTextSubmit(text);
    }

    textInput.value = '';
    textInput.style.height = 'auto';
    sendBtn.disabled = true;
}

// ── PHOTO_TEXT: 사진+텍스트 제출 → AI 분석 ──
async function handlePhotoTextSubmit(text) {
    // 사용자 메시지 표시
    if (reportData.photos.length > 0 || text) {
        appendUser(text, reportData.photos);
    }
    reportData.description = text;

    setInputDisabled(true);
    showTyping();

    // AI 분석 호출
    try {
        const categoriesForAI = {};
        for (const [type, cats] of Object.entries(refData.categories)) {
            categoriesForAI[type] = cats.map(c => ({ id: c.category_id, name: c.category_name }));
        }

        const res = await fetch(`${AI_API_BASE}/chatbot/analyze`, {
            method: 'POST',
            headers: { ...getHeaders(), 'Content-Type': 'application/json' },
            body: JSON.stringify({ user_text: text || '사진 참고', categories: categoriesForAI }),
        });

        if (res.ok) {
            aiAnalysis = await res.json();
        } else {
            aiAnalysis = { organized_description: text, suggested_type: null, confidence: 0 };
        }
    } catch (err) {
        console.error('AI 분석 실패:', err);
        aiAnalysis = { organized_description: text, suggested_type: null, confidence: 0 };
    }

    hideTyping();
    reportData.organized_description = aiAnalysis.organized_description || text;

    // 유형 선택 단계로
    currentState = STATE.CLASSIFY_TYPE;
    showTypeSelection();
    setInputDisabled(true);
}

// ── CLASSIFY_TYPE: 유형 선택 ──
function showTypeSelection() {
    const typeLabels = {
        nonconformity: '부적합',
        facility: '시설설비',
        safety: '안전',
    };

    let msg = '내용을 분석했습니다.';
    if (aiAnalysis && aiAnalysis.organized_description) {
        msg += `\n\n📝 "${escapeHtml(aiAnalysis.organized_description)}"`;
    }
    msg += '\n\n신고 **유형**을 선택해주세요:';
    appendBot(msg);

    const options = Object.entries(typeLabels).map(([value, label]) => ({
        value, label,
        suggested: aiAnalysis && aiAnalysis.suggested_type === value,
    }));
    appendOptions(options, onTypeSelect);
}

function onTypeSelect(type) {
    reportData.issue_type = type;
    const label = { nonconformity: '부적합', facility: '시설설비', safety: '안전' }[type];
    appendUser(label);
    disableCurrentOptions();

    currentState = STATE.CLASSIFY_CATEGORY;
    showCategorySelection();
}

// ── CLASSIFY_CATEGORY ──
function showCategorySelection() {
    const cats = refData.categories[reportData.issue_type] || [];
    if (cats.length === 0) {
        appendBot('해당 유형의 카테고리가 없습니다. 다음 단계로 진행합니다.');
        currentState = STATE.LOCATION;
        showLocationSelection();
        return;
    }

    appendBot('**카테고리**를 선택해주세요:');

    const options = cats.map(c => ({
        value: c.category_id,
        label: c.category_name,
        suggested: aiAnalysis && aiAnalysis.suggested_category_id === c.category_id,
    }));
    appendOptions(options, onCategorySelect);
}

async function onCategorySelect(categoryId) {
    const cats = refData.categories[reportData.issue_type] || [];
    const cat = cats.find(c => c.category_id == categoryId);
    reportData.issue_category_id = categoryId;
    reportData.issue_category_name = cat ? cat.category_name : '';
    appendUser(reportData.issue_category_name);
    disableCurrentOptions();

    // 항목 로드
    currentState = STATE.CLASSIFY_ITEM;
    await showItemSelection(categoryId);
}

// ── CLASSIFY_ITEM ──
async function showItemSelection(categoryId) {
    if (!refData.items[categoryId]) {
        try {
            const res = await fetch(`${API_BASE}/work-issues/items/category/${categoryId}`, { headers: getHeaders() });
            if (res.ok) {
                const d = await res.json();
                refData.items[categoryId] = d.data || [];
            }
        } catch (err) {
            console.error('항목 로드 실패:', err);
        }
    }

    const items = refData.items[categoryId] || [];
    if (items.length === 0) {
        appendBot('항목이 없습니다. 다음 단계로 진행합니다.');
        currentState = STATE.LOCATION;
        showLocationSelection();
        return;
    }

    appendBot('**세부 항목**을 선택해주세요:');

    const options = items.map(i => ({ value: i.item_id, label: i.item_name }));
    options.push({ value: '__custom__', label: '+ 직접 입력' });
    appendOptions(options, onItemSelect);
}

function onItemSelect(itemValue) {
    if (itemValue === '__custom__') {
        disableCurrentOptions();
        showCustomItemInput();
        return;
    }
    const items = refData.items[reportData.issue_category_id] || [];
    const item = items.find(i => i.item_id == itemValue);
    reportData.issue_item_id = itemValue;
    reportData.issue_item_name = item ? item.item_name : '';
    reportData.custom_item_name = null;
    appendUser(reportData.issue_item_name);
    disableCurrentOptions();

    currentState = STATE.LOCATION;
    showLocationSelection();
}

function showCustomItemInput() {
    appendBot('항목명을 직접 입력해주세요:');
    setInputDisabled(false);
    textInput.placeholder = '항목명 입력...';
    // Temporarily override send for custom item
    const origOnSend = onSend;
    sendBtn.onclick = () => {
        const val = textInput.value.trim();
        if (!val) return;
        reportData.custom_item_name = val;
        reportData.issue_item_id = null;
        reportData.issue_item_name = val;
        appendUser(val);
        textInput.value = '';
        textInput.style.height = 'auto';
        textInput.placeholder = '메시지 입력...';
        sendBtn.onclick = onSend;
        setInputDisabled(true);
        currentState = STATE.LOCATION;
        showLocationSelection();
    };
    textInput.onkeydown = (e) => {
        if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendBtn.click(); }
    };
}

// ── LOCATION: 작업장 선택 ──
function showLocationSelection() {
    appendBot('**위치(작업장)**를 선택해주세요:');

    const options = [];
    refData.factories.forEach(factory => {
        // 해당 공장의 TBM 작업장만 우선 표시
        const factoryTbm = refData.tbmSessions.filter(s => {
            // Check if workplace belongs to this factory
            return true; // We'll show all workplaces by factory group
        });

        options.push({
            value: `factory_${factory.category_id}`,
            label: `🏭 ${factory.category_name}`,
            isGroup: true,
        });
    });

    // 작업장 로드 후 표시 (공장별)
    loadWorkplacesAndShow();
}

async function loadWorkplacesAndShow() {
    const allOptions = [];

    for (const factory of refData.factories) {
        // 작업장 로드 (맵 리전에서)
        if (!refData.workplaces[factory.category_id]) {
            try {
                const res = await fetch(`${API_BASE}/workplaces/categories/${factory.category_id}/map-regions`, { headers: getHeaders() });
                if (res.ok) {
                    const d = await res.json();
                    refData.workplaces[factory.category_id] = (d.data || []).map(r => ({
                        workplace_id: r.workplace_id,
                        workplace_name: r.workplace_name,
                        factory_id: factory.category_id,
                        factory_name: factory.category_name,
                    }));
                }
            } catch (err) {
                console.error(`작업장 로드 실패 (${factory.category_name}):`, err);
            }
        }

        const workplaces = refData.workplaces[factory.category_id] || [];

        if (workplaces.length > 0) {
            // 해당 공장에 TBM이 있는 작업장 표시
            const tbmWorkplaceIds = new Set(
                refData.tbmSessions
                    .filter(s => workplaces.some(w => w.workplace_id === s.workplace_id))
                    .map(s => s.workplace_id)
            );

            workplaces.forEach(wp => {
                const hasTbm = tbmWorkplaceIds.has(wp.workplace_id);
                allOptions.push({
                    value: JSON.stringify({ fid: factory.category_id, fname: factory.category_name, wid: wp.workplace_id, wname: wp.workplace_name }),
                    label: `${factory.category_name} - ${wp.workplace_name}${hasTbm ? ' 🔨' : ''}`,
                });
            });
        }
    }

    allOptions.push({ value: '__unknown__', label: '📍 위치 모름 / 직접 입력' });

    appendOptions(allOptions, onLocationSelect);
}

function onLocationSelect(value) {
    disableCurrentOptions();
    if (value === '__unknown__') {
        reportData.factory_category_id = null;
        reportData.workplace_id = null;
        reportData.workplace_name = null;
        appendUser('위치 모름');

        // 직접 입력
        appendBot('위치를 직접 입력해주세요 (또는 "모름"이라고 입력):');
        setInputDisabled(false);
        textInput.placeholder = '위치 입력...';
        sendBtn.onclick = () => {
            const val = textInput.value.trim();
            if (!val) return;
            reportData.custom_location = val === '모름' ? null : val;
            appendUser(val);
            textInput.value = '';
            textInput.style.height = 'auto';
            textInput.placeholder = '메시지 입력...';
            sendBtn.onclick = onSend;
            setInputDisabled(true);
            currentState = STATE.PROJECT;
            showProjectSelection();
        };
        textInput.onkeydown = (e) => {
            if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendBtn.click(); }
        };
        return;
    }

    try {
        const loc = JSON.parse(value);
        reportData.factory_category_id = loc.fid;
        reportData.factory_name = loc.fname;
        reportData.workplace_id = loc.wid;
        reportData.workplace_name = loc.wname;
        reportData.custom_location = null;
        appendUser(`${loc.fname} - ${loc.wname}`);
    } catch (e) {
        appendUser(value);
    }

    currentState = STATE.PROJECT;
    showProjectSelection();
}

// ── PROJECT: 프로젝트 선택 ──
function showProjectSelection() {
    appendBot('**프로젝트**를 선택해주세요:');

    const options = [];

    // TBM 세션에서 프로젝트 정보 (해당 작업장 우선)
    const tbmProjectIds = new Set();
    const relevantTbm = reportData.workplace_id
        ? refData.tbmSessions.filter(s => s.workplace_id === reportData.workplace_id)
        : refData.tbmSessions;

    relevantTbm.forEach(s => {
        if (s.project_id) {
            const proj = refData.projects.find(p => p.project_id === s.project_id);
            if (proj && !tbmProjectIds.has(s.project_id)) {
                tbmProjectIds.add(s.project_id);
                const memberCount = s.team_member_count || s.member_count || 0;
                options.push({
                    value: JSON.stringify({ pid: proj.project_id, pname: proj.project_name, sid: s.session_id }),
                    label: `🔨 ${proj.project_name} (TBM ${memberCount}명)`,
                });
            }
        }
    });

    // 나머지 활성 프로젝트
    refData.projects.forEach(p => {
        if (!tbmProjectIds.has(p.project_id)) {
            options.push({
                value: JSON.stringify({ pid: p.project_id, pname: p.project_name, sid: null }),
                label: p.project_name,
            });
        }
    });

    options.push({ value: '__unknown__', label: '프로젝트 모름 (건너뛰기)' });

    appendOptions(options, onProjectSelect);
}

function onProjectSelect(value) {
    disableCurrentOptions();
    if (value === '__unknown__') {
        reportData.project_id = null;
        reportData.project_name = null;
        reportData.tbm_session_id = null;
        appendUser('프로젝트 모름');
    } else {
        try {
            const proj = JSON.parse(value);
            reportData.project_id = proj.pid;
            reportData.project_name = proj.pname;
            reportData.tbm_session_id = proj.sid;
            appendUser(proj.pname);
        } catch (e) {
            appendUser(value);
        }
    }

    currentState = STATE.CONFIRM;
    showConfirmation();
}

// ── CONFIRM: 요약 확인 ──
async function showConfirmation() {
    showTyping();

    // AI 요약 호출
    let summaryText = '';
    try {
        const typeLabel = { nonconformity: '부적합', facility: '시설설비', safety: '안전' }[reportData.issue_type] || '';
        const res = await fetch(`${AI_API_BASE}/chatbot/summarize`, {
            method: 'POST',
            headers: { ...getHeaders(), 'Content-Type': 'application/json' },
            body: JSON.stringify({
                description: reportData.organized_description || reportData.description,
                type: typeLabel,
                category: reportData.issue_category_name || '',
                item: reportData.issue_item_name || reportData.custom_item_name || '',
                location: reportData.workplace_name
                    ? `${reportData.factory_name || ''} - ${reportData.workplace_name}`
                    : (reportData.custom_location || '미지정'),
                project: reportData.project_name || '미지정',
            }),
        });
        if (res.ok) {
            const d = await res.json();
            summaryText = d.summary || '';
        }
    } catch (err) {
        console.error('AI 요약 실패:', err);
    }

    hideTyping();

    appendBot('신고 내용을 확인해주세요:');

    // Summary card
    const typeLabel = { nonconformity: '부적합', facility: '시설설비', safety: '안전' }[reportData.issue_type] || '';
    const locationText = reportData.workplace_name
        ? `${reportData.factory_name || ''} - ${reportData.workplace_name}`
        : (reportData.custom_location || '미지정');

    const card = document.createElement('div');
    card.className = 'summary-card';
    card.innerHTML = `
        <div class="summary-title">📋 신고 요약</div>
        <div class="summary-row"><span class="summary-label">유형</span><span class="summary-value">${escapeHtml(typeLabel)}</span></div>
        <div class="summary-row"><span class="summary-label">카테고리</span><span class="summary-value">${escapeHtml(reportData.issue_category_name || '-')}</span></div>
        <div class="summary-row"><span class="summary-label">항목</span><span class="summary-value">${escapeHtml(reportData.issue_item_name || reportData.custom_item_name || '-')}</span></div>
        <div class="summary-row"><span class="summary-label">위치</span><span class="summary-value">${escapeHtml(locationText)}</span></div>
        <div class="summary-row"><span class="summary-label">프로젝트</span><span class="summary-value">${escapeHtml(reportData.project_name || '미지정')}</span></div>
        <div class="summary-row"><span class="summary-label">내용</span><span class="summary-value">${escapeHtml(reportData.organized_description || reportData.description || '-')}</span></div>
        ${reportData.photos.length > 0 ? `<div class="summary-row"><span class="summary-label">사진</span><span class="summary-value">${reportData.photos.length}장 첨부</span></div>` : ''}
        ${summaryText ? `<div style="margin-top:0.5rem;padding-top:0.5rem;border-top:1px solid #e2e8f0;font-size:0.8125rem;color:#64748b;">${escapeHtml(summaryText)}</div>` : ''}
    `;
    chatArea.appendChild(card);

    // Actions
    const actions = document.createElement('div');
    actions.className = 'summary-actions';
    actions.innerHTML = `
        <button class="btn-submit" id="confirmSubmitBtn">✅ 제출하기</button>
        <button class="btn-edit" id="confirmEditBtn">✏️ 처음부터</button>
    `;
    chatArea.appendChild(actions);
    scrollToBottom();

    document.getElementById('confirmSubmitBtn').addEventListener('click', () => {
        actions.remove();
        submitReport();
    });
    document.getElementById('confirmEditBtn').addEventListener('click', () => {
        window.location.reload();
    });

    setInputDisabled(true);
}

// ── SUBMIT: 제출 ──
async function submitReport() {
    currentState = STATE.SUBMIT;
    appendUser('제출하기');

    const loading = document.createElement('div');
    loading.className = 'chat-loading';
    loading.innerHTML = '<div class="chat-loading-inner">신고를 접수하고 있습니다...</div>';
    document.body.appendChild(loading);

    try {
        const requestBody = {
            factory_category_id: reportData.factory_category_id || null,
            workplace_id: reportData.workplace_id || null,
            custom_location: reportData.custom_location || null,
            project_id: reportData.project_id || null,
            tbm_session_id: reportData.tbm_session_id || null,
            visit_request_id: null,
            issue_category_id: reportData.issue_category_id,
            issue_item_id: reportData.issue_item_id || null,
            custom_item_name: reportData.custom_item_name || null,
            additional_description: reportData.organized_description || reportData.description || null,
            photos: reportData.photos,
        };

        const res = await fetch(`${API_BASE}/work-issues`, {
            method: 'POST',
            headers: { ...getHeaders(), 'Content-Type': 'application/json' },
            body: JSON.stringify(requestBody),
        });

        const data = await res.json();
        loading.remove();

        if (data.success) {
            const isNonconformity = reportData.issue_type === 'nonconformity';
            const typeLabel = { nonconformity: '부적합', facility: '시설설비', safety: '안전' }[reportData.issue_type] || '';
            const destMsg = isNonconformity
                ? 'TKQC 수신함에서 확인하실 수 있습니다.'
                : `${typeLabel} 신고 현황에서 확인하실 수 있습니다.`;
            appendBot(`✅ **신고가 성공적으로 접수되었습니다!**\n\n접수된 신고는 ${destMsg}`);

            const linkDiv = document.createElement('div');
            linkDiv.className = 'summary-actions';
            if (isNonconformity) {
                linkDiv.innerHTML = `
                    <button class="btn-submit" onclick="window.location.href=(location.hostname.includes('technicalkorea.net') ? 'https://tkqc.technicalkorea.net' : location.protocol + '//' + location.hostname + ':30280')">📋 TKQC 수신함</button>
                    <button class="btn-edit" onclick="window.location.reload()">➕ 새 신고</button>
                `;
            } else {
                linkDiv.innerHTML = `
                    <button class="btn-submit" onclick="window.location.href='/pages/safety/report-status.html'">📋 신고 현황</button>
                    <button class="btn-edit" onclick="window.location.reload()">➕ 새 신고</button>
                `;
            }
            chatArea.appendChild(linkDiv);
            scrollToBottom();
        } else {
            throw new Error(data.error || '신고 등록 실패');
        }
    } catch (err) {
        loading.remove();
        console.error('신고 제출 실패:', err);
        appendBot(`❌ 신고 접수에 실패했습니다: ${escapeHtml(err.message)}\n\n다시 시도해주세요.`);

        const retryDiv = document.createElement('div');
        retryDiv.className = 'summary-actions';
        retryDiv.innerHTML = `
            <button class="btn-submit" id="retrySubmitBtn">🔄 다시 시도</button>
            <button class="btn-edit" onclick="window.location.reload()">처음부터</button>
        `;
        chatArea.appendChild(retryDiv);
        document.getElementById('retrySubmitBtn').addEventListener('click', () => {
            retryDiv.remove();
            submitReport();
        });
        scrollToBottom();
    }
}

// ── 사진 처리 ──
function onPhotoSelect(e) {
    const file = e.target.files[0];
    if (!file) return;
    if (reportData.photos.length >= 5) return;

    processPhoto(file);
    e.target.value = '';
}

async function processPhoto(file) {
    // 1단계: 브라우저가 직접 처리 (JPEG/PNG/WebP, iOS Safari HEIC)
    try {
        const dataUrl = await resizeImage(file, 1280, 0.8);
        reportData.photos.push(dataUrl);
        updatePhotoCount();
        sendBtn.disabled = false;
        return;
    } catch (e) {
        // 브라우저가 직접 처리 못하는 형식 (HEIC on Chrome 등)
    }

    // 2단계: 원본 파일을 base64로 읽어서 그대로 전송 (서버 sharp가 JPEG 변환)
    const reader = new FileReader();
    reader.onload = (ev) => {
        reportData.photos.push(ev.target.result);
        updatePhotoCount();
        sendBtn.disabled = false;
    };
    reader.readAsDataURL(file);
}

/**
 * 이미지 리사이징 (기존 issue-report.js와 동일 패턴)
 */
function resizeImage(file, maxSize, quality) {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => {
            let w = img.width, h = img.height;
            if (w > maxSize || h > maxSize) {
                if (w > h) { h = Math.round(h * maxSize / w); w = maxSize; }
                else { w = Math.round(w * maxSize / h); h = maxSize; }
            }
            const cvs = document.createElement('canvas');
            cvs.width = w; cvs.height = h;
            cvs.getContext('2d').drawImage(img, 0, 0, w, h);
            resolve(cvs.toDataURL('image/jpeg', quality));
        };
        img.onerror = reject;
        img.src = URL.createObjectURL(file);
    });
}

function updatePhotoCount() {
    const countEl = photoBtn.querySelector('.photo-count');
    if (reportData.photos.length > 0) {
        if (countEl) {
            countEl.textContent = reportData.photos.length;
        } else {
            const badge = document.createElement('span');
            badge.className = 'photo-count';
            badge.textContent = reportData.photos.length;
            photoBtn.appendChild(badge);
        }
    } else if (countEl) {
        countEl.remove();
    }
}


// ── UI 헬퍼 ──

function appendBot(text) {
    const msg = document.createElement('div');
    msg.className = 'chat-msg bot';
    msg.innerHTML = `
        <div class="chat-avatar">🤖</div>
        <div class="chat-bubble">${formatMessage(text)}</div>
    `;
    chatArea.appendChild(msg);
    scrollToBottom();
}

function appendUser(text, photos) {
    const msg = document.createElement('div');
    msg.className = 'chat-msg user';

    let photoHtml = '';
    if (photos && photos.length > 0) {
        photoHtml = '<div class="chat-photos">' +
            photos.map((p, i) => `<img src="${p}" alt="첨부 사진" onerror="this.style.display='none';this.insertAdjacentHTML('afterend','<div class=\\'photo-fallback\\'>📷 사진 ${i+1}</div>')">`).join('') +
            '</div>';
    }

    msg.innerHTML = `
        <div class="chat-avatar">👤</div>
        <div class="chat-bubble">${escapeHtml(text || '')}${photoHtml}</div>
    `;
    chatArea.appendChild(msg);
    scrollToBottom();
}

function appendOptions(options, callback) {
    const container = document.createElement('div');
    container.className = 'chat-options';
    container.dataset.active = 'true';

    options.forEach(opt => {
        if (opt.isGroup) return; // Skip group headers
        const btn = document.createElement('button');
        btn.className = 'chat-option-btn' + (opt.suggested ? ' suggested' : '');
        btn.textContent = opt.label;
        btn.addEventListener('click', () => {
            callback(opt.value);
        });
        container.appendChild(btn);
    });

    chatArea.appendChild(container);
    scrollToBottom();
}

function disableCurrentOptions() {
    chatArea.querySelectorAll('.chat-options[data-active="true"]').forEach(el => {
        el.dataset.active = 'false';
        el.querySelectorAll('.chat-option-btn').forEach(btn => {
            btn.style.pointerEvents = 'none';
            btn.style.opacity = '0.5';
        });
    });
}

let typingEl = null;
function showTyping() {
    if (typingEl) return;
    typingEl = document.createElement('div');
    typingEl.className = 'chat-msg bot';
    typingEl.innerHTML = `
        <div class="chat-avatar">🤖</div>
        <div class="chat-bubble"><div class="typing-indicator"><span></span><span></span><span></span></div></div>
    `;
    chatArea.appendChild(typingEl);
    scrollToBottom();
}

function hideTyping() {
    if (typingEl) { typingEl.remove(); typingEl = null; }
}

function setInputDisabled(disabled) {
    const bar = document.querySelector('.chat-input-bar');
    if (disabled) {
        bar.classList.add('disabled');
    } else {
        bar.classList.remove('disabled');
        textInput.focus();
    }
}

function updateInputBar() {
    setInputDisabled(currentState !== STATE.PHOTO_TEXT);
}

function scrollToBottom() {
    requestAnimationFrame(() => {
        chatArea.scrollTop = chatArea.scrollHeight;
    });
}

function formatMessage(text) {
    // Simple markdown: **bold**, \n → <br>
    return text
        .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
        .replace(/\n/g, '<br>');
}

function getHeaders() {
    const token = window.getSSOToken ? window.getSSOToken() : localStorage.getItem('sso_token');
    return { 'Authorization': token ? `Bearer ${token}` : '' };
}
