// 자동매매 페이지 클라이언트 스크립트

let logLevelFilter = 'all'; // 'all' | 'action'
let watchSource = { useScanner: true, selectedThemes: [] };
let localLogs = []; // 클라이언트 로그 버퍼 (오래된 것 → 최신 순)
let tradeLogWS = null;

document.addEventListener('DOMContentLoaded', () => {
    loadStatus();
    loadPositions();
    loadLogs();   // 기존 로그 초기 로드 (HTTP)
    loadRules();
    loadThemeList();
    loadWatchSource();
    connectTradeLogWS(); // WS 실시간 연결

    // 자동스크롤 체크박스: ON 전환 시 즉시 최신으로 이동
    const chk = document.getElementById('autoScrollChk');
    if (chk) {
        chk.addEventListener('change', () => {
            if (chk.checked) scrollLogsToBottom();
        });
    }

    // 상태: 3초 주기, 포지션: 5초 주기 (로그는 WS로 대체)
    setInterval(loadStatus, 3000);
    setInterval(loadPositions, 5000);
});

// --- 엔진 상태 ---

async function loadStatus() {
    try {
        const res = await fetch('/api/autotrade/status');
        const data = await res.json();
        updateStatusUI(data);
    } catch (e) {
        console.error('상태 조회 실패:', e);
    }
}

function updateStatusUI(data) {
    const dot  = document.getElementById('statusDot');
    const text = document.getElementById('statusText');

    if (data.running) {
        dot.className  = 'w-3 h-3 rounded-full bg-green-500';
        text.textContent = '● 실행중';
        text.className = 'text-sm font-medium text-green-600';
    } else {
        dot.className  = 'w-3 h-3 rounded-full bg-gray-300';
        text.textContent = '○ 중지';
        text.className = 'text-sm font-medium text-gray-500';
    }

    document.getElementById('statActivePos').textContent   = data.activePositions ?? 0;
    document.getElementById('statTradeCount').textContent  = data.tradeCount ?? 0;

    const pl = data.totalPL ?? 0;
    const plEl = document.getElementById('statTotalPL');
    plEl.textContent = formatMoney(pl) + '원';
    plEl.className = 'text-2xl font-bold ' + (pl > 0 ? 'text-red-500' : pl < 0 ? 'text-blue-500' : 'text-gray-800');
}

// --- 엔진 제어 ---

async function startEngine() {
    if (!confirm('자동매매 엔진을 시작하시겠습니까?')) return;
    try {
        await fetch('/api/autotrade/start', { method: 'POST' });
        await loadStatus();
    } catch (e) {
        alert('엔진 시작 실패: ' + e.message);
    }
}

async function stopEngine() {
    if (!confirm('자동매매 엔진을 중지하시겠습니까?')) return;
    try {
        await fetch('/api/autotrade/stop', { method: 'POST' });
        await loadStatus();
    } catch (e) {
        alert('엔진 중지 실패: ' + e.message);
    }
}

async function emergencyStop() {
    if (!confirm('⚠ 긴급청산: 모든 포지션을 즉시 시장가 매도합니다.\n계속하시겠습니까?')) return;
    try {
        await fetch('/api/autotrade/emergency', { method: 'POST' });
        await loadStatus();
        await loadPositions();
    } catch (e) {
        alert('긴급청산 실패: ' + e.message);
    }
}

// --- 규칙 ---

async function loadRules() {
    try {
        const res = await fetch('/api/autotrade/rules');
        const rules = await res.json();
        renderRules(rules);
    } catch (e) {
        console.error('규칙 조회 실패:', e);
    }
}

function renderRules(rules) {
    const el = document.getElementById('rulesList');
    if (!rules || rules.length === 0) {
        el.innerHTML = '<p class="text-xs text-gray-400 text-center py-4">규칙이 없습니다.</p>';
        return;
    }
    el.innerHTML = rules.map(r => `
        <div class="border border-gray-100 rounded-lg p-3 space-y-2">
            <div class="flex items-center justify-between">
                <span class="text-sm font-semibold text-gray-800">${escHtml(r.name)}</span>
                <label class="inline-flex items-center cursor-pointer">
                    <input type="checkbox" ${r.enabled ? 'checked' : ''} onchange="toggleRule('${r.id}')"
                        class="sr-only peer">
                    <div class="w-9 h-5 bg-gray-200 peer-checked:bg-blue-600 rounded-full peer
                        peer-focus:ring-2 peer-focus:ring-blue-300 transition-colors relative
                        after:content-[''] after:absolute after:top-[2px] after:left-[2px]
                        after:bg-white after:rounded-full after:h-4 after:w-4 after:transition-all
                        peer-checked:after:translate-x-4"></div>
                </label>
            </div>
            <div class="text-xs text-gray-500 space-y-0.5">
                <p>진입: RiseScore≥${r.minRiseScore} / 체결강도≥${r.minCntrStr}${r.requireBullish ? ' / AI호재' : ''}</p>
                <p>청산: 손절${r.stopLossPct}% / 익절+${r.takeProfitPct}%${r.maxHoldMinutes > 0 ? ' / ' + r.maxHoldMinutes + '분' : ''}${r.exitBeforeClose ? ' / 장마감전' : ''}</p>
                <p>주문금액: ${formatMoney(r.orderAmount)}원 / 최대${r.maxPositions}종목</p>
            </div>
            <div class="flex gap-2">
                <button onclick="showEditRuleModal(${JSON.stringify(r).replace(/"/g, '&quot;')})"
                    class="px-2 py-1 text-xs text-blue-600 border border-blue-200 rounded hover:bg-blue-50 transition-colors">수정</button>
                <button onclick="deleteRule('${r.id}')"
                    class="px-2 py-1 text-xs text-red-500 border border-red-200 rounded hover:bg-red-50 transition-colors">삭제</button>
            </div>
        </div>
    `).join('');
}

async function deleteRule(id) {
    if (!confirm('규칙을 삭제하시겠습니까?')) return;
    try {
        await fetch('/api/autotrade/rules/' + id, { method: 'DELETE' });
        await loadRules();
    } catch (e) {
        alert('삭제 실패: ' + e.message);
    }
}

async function toggleRule(id) {
    try {
        await fetch('/api/autotrade/rules/' + id + '/toggle', { method: 'POST' });
        await loadRules();
    } catch (e) {
        alert('토글 실패: ' + e.message);
    }
}

// --- 모달 ---

function showAddRuleModal() {
    document.getElementById('modalTitle').textContent = '규칙 추가';
    document.getElementById('ruleId').value = '';
    document.getElementById('fName').value = '';
    document.getElementById('fRiseScore').value = 60;
    document.getElementById('riseScoreVal').textContent = '60';
    document.getElementById('fCntrStr').value = 110;
    document.getElementById('fRequireBullish').checked = false;
    document.getElementById('fOrderAmount').value = 500000;
    document.getElementById('fMaxPositions').value = 3;
    document.getElementById('fStopLoss').value = -3;
    document.getElementById('fTakeProfit').value = 5;
    document.getElementById('fMaxHold').value = 60;
    document.getElementById('fExitBeforeClose').checked = true;
    document.getElementById('ruleModal').classList.remove('hidden');
}

function showEditRuleModal(r) {
    document.getElementById('modalTitle').textContent = '규칙 수정';
    document.getElementById('ruleId').value = r.id;
    document.getElementById('fName').value = r.name;
    document.getElementById('fRiseScore').value = r.minRiseScore;
    document.getElementById('riseScoreVal').textContent = r.minRiseScore;
    document.getElementById('fCntrStr').value = r.minCntrStr;
    document.getElementById('fRequireBullish').checked = r.requireBullish;
    document.getElementById('fOrderAmount').value = r.orderAmount;
    document.getElementById('fMaxPositions').value = r.maxPositions;
    document.getElementById('fStopLoss').value = r.stopLossPct;
    document.getElementById('fTakeProfit').value = r.takeProfitPct;
    document.getElementById('fMaxHold').value = r.maxHoldMinutes;
    document.getElementById('fExitBeforeClose').checked = r.exitBeforeClose;
    document.getElementById('ruleModal').classList.remove('hidden');
}

function hideModal() {
    document.getElementById('ruleModal').classList.add('hidden');
}

async function submitRule() {
    const id   = document.getElementById('ruleId').value;
    const rule = {
        name:            document.getElementById('fName').value.trim(),
        enabled:         true,
        minRiseScore:    parseInt(document.getElementById('fRiseScore').value),
        minCntrStr:      parseFloat(document.getElementById('fCntrStr').value),
        requireBullish:  document.getElementById('fRequireBullish').checked,
        orderAmount:     parseInt(document.getElementById('fOrderAmount').value),
        maxPositions:    parseInt(document.getElementById('fMaxPositions').value),
        stopLossPct:     parseFloat(document.getElementById('fStopLoss').value),
        takeProfitPct:   parseFloat(document.getElementById('fTakeProfit').value),
        maxHoldMinutes:  parseInt(document.getElementById('fMaxHold').value),
        exitBeforeClose: document.getElementById('fExitBeforeClose').checked,
    };

    if (!rule.name) { alert('규칙명을 입력해주세요.'); return; }

    try {
        if (id) {
            await fetch('/api/autotrade/rules/' + id, {
                method: 'PUT',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(rule),
            });
        } else {
            await fetch('/api/autotrade/rules', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(rule),
            });
        }
        hideModal();
        await loadRules();
    } catch (e) {
        alert('저장 실패: ' + e.message);
    }
}

// --- 포지션 ---

async function loadPositions() {
    try {
        const res = await fetch('/api/autotrade/positions');
        const positions = await res.json();
        renderPositions(positions);
    } catch (e) {
        console.error('포지션 조회 실패:', e);
    }
}

function renderPositions(positions) {
    const el = document.getElementById('positionsList');
    const active = (positions || []).filter(p => p.status === 'open' || p.status === 'pending');

    if (active.length === 0) {
        el.innerHTML = '<p class="text-xs text-gray-400 text-center py-4">보유 포지션 없음</p>';
        return;
    }

    el.innerHTML = `
        <table class="w-full text-xs">
            <thead>
                <tr class="text-left text-gray-400 border-b border-gray-100">
                    <th class="pb-2 font-medium">종목</th>
                    <th class="pb-2 font-medium text-right">매수가</th>
                    <th class="pb-2 font-medium text-right">수량</th>
                    <th class="pb-2 font-medium text-right">손절가</th>
                    <th class="pb-2 font-medium text-center">상태</th>
                </tr>
            </thead>
            <tbody>
                ${active.map(p => {
                    const statusCls = p.status === 'open' ? 'text-green-600' : 'text-yellow-600';
                    const statusTxt = p.status === 'open' ? '보유중' : '체결대기';
                    return `
                        <tr class="border-b border-gray-50">
                            <td class="py-2">
                                <div class="font-medium text-gray-800">${escHtml(p.name)}</div>
                                <div class="text-gray-400">${p.code}</div>
                            </td>
                            <td class="py-2 text-right text-gray-700">${formatMoney(p.buyPrice)}</td>
                            <td class="py-2 text-right text-gray-700">${p.qty}</td>
                            <td class="py-2 text-right text-blue-500">${formatMoney(p.stopLoss)}</td>
                            <td class="py-2 text-center font-medium ${statusCls}">${statusTxt}</td>
                        </tr>
                    `;
                }).join('')}
            </tbody>
        </table>
    `;
}

// --- 감시 소스 ---

async function loadThemeList() {
    try {
        const res = await fetch('/api/themes?date=1&sort=3');
        const themes = await res.json();
        const sel = document.getElementById('themeSelect');
        if (!sel || !themes) return;
        // 가나다순 정렬 후 추가
        const sorted = [...themes].sort((a, b) => a.name.localeCompare(b.name, 'ko'));
        sel.innerHTML = '<option value="">테마를 선택하세요...</option>';
        sorted.forEach(t => {
            const opt = document.createElement('option');
            opt.value = t.code;
            opt.textContent = `${t.name} (${t.fluRt >= 0 ? '+' : ''}${t.fluRt.toFixed(2)}%)`;
            opt.dataset.name = t.name;
            sel.appendChild(opt);
        });
    } catch (e) {
        console.error('테마 목록 조회 실패:', e);
    }
}

async function loadWatchSource() {
    try {
        const res = await fetch('/api/autotrade/watch-source');
        watchSource = await res.json();
        renderWatchSource();
    } catch (e) {
        console.error('감시 소스 조회 실패:', e);
    }
}

async function saveWatchSource() {
    const scannerChk = document.getElementById('wsScanner');
    watchSource.useScanner = scannerChk ? scannerChk.checked : true;
    try {
        await fetch('/api/autotrade/watch-source', {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(watchSource),
        });
    } catch (e) {
        alert('감시 소스 저장 실패: ' + e.message);
    }
}

function renderWatchSource() {
    const scannerChk = document.getElementById('wsScanner');
    if (scannerChk) scannerChk.checked = watchSource.useScanner;

    const container = document.getElementById('selectedThemes');
    const noMsg = document.getElementById('noThemeMsg');
    if (!container) return;

    const themes = watchSource.selectedThemes || [];
    if (themes.length === 0) {
        container.innerHTML = '<span class="text-xs text-gray-400" id="noThemeMsg">선택된 테마 없음</span>';
        return;
    }

    container.innerHTML = themes.map(t => `
        <span class="inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-700">
            ${escHtml(t.name)}
            <button onclick="removeTheme('${escHtml(t.code)}')" class="hover:text-blue-900 text-blue-400 font-bold leading-none">×</button>
        </span>
    `).join('');
}

function addSelectedTheme() {
    const sel = document.getElementById('themeSelect');
    if (!sel || !sel.value) return;
    const code = sel.value;
    const name = sel.options[sel.selectedIndex]?.dataset.name || sel.options[sel.selectedIndex]?.text || code;

    if (!watchSource.selectedThemes) watchSource.selectedThemes = [];
    if (watchSource.selectedThemes.some(t => t.code === code)) {
        alert('이미 추가된 테마입니다.');
        return;
    }
    watchSource.selectedThemes.push({ code, name });
    renderWatchSource();
    saveWatchSource();
    sel.value = '';
}

function removeTheme(code) {
    if (!watchSource.selectedThemes) return;
    watchSource.selectedThemes = watchSource.selectedThemes.filter(t => t.code !== code);
    renderWatchSource();
    saveWatchSource();
}

// --- 로그 ---

// --- WS 실시간 로그 ---

function connectTradeLogWS() {
    const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
    tradeLogWS = new WebSocket(`${proto}//${location.host}/ws`);

    tradeLogWS.onopen = () => {
        updateWSStatus(true);
    };

    tradeLogWS.onmessage = (e) => {
        let msg;
        try { msg = JSON.parse(e.data); } catch { return; }
        if (msg.type !== 'tradelog') return;
        const log = msg.data;
        localLogs.push(log);
        if (localLogs.length > 300) localLogs.shift();

        // 필터 조건에 맞으면 DOM에 행 추가
        if (logLevelFilter !== 'action' || log.level !== 'debug') {
            appendLogRow(log);
        }
        updateLogTime();
    };

    tradeLogWS.onclose = () => {
        updateWSStatus(false);
        // 3초 후 재연결 + 로그 재로드
        setTimeout(() => {
            loadLogs();
            connectTradeLogWS();
        }, 3000);
    };

    tradeLogWS.onerror = () => {
        tradeLogWS.close();
    };
}

function updateWSStatus(connected) {
    const el = document.getElementById('wsStatus');
    if (!el) return;
    el.textContent = connected ? '● 실시간' : '○ 연결중...';
    el.className = connected
        ? 'text-xs text-green-500 font-medium'
        : 'text-xs text-gray-400';
}

function scrollLogsToBottom() {
    const wrapper = document.getElementById('logsWrapper');
    if (wrapper) wrapper.scrollTop = wrapper.scrollHeight;
}

function updateLogTime() {
    const el = document.getElementById('logUpdateTime');
    if (el) el.textContent = new Date().toLocaleTimeString('ko-KR',
        { hour: '2-digit', minute: '2-digit', second: '2-digit' }) + ' 갱신';
}

function buildLogRow(l) {
    let rowCls, levelCls, msgCls;
    if (l.level === 'debug') {
        rowCls   = 'border-b border-gray-50 bg-gray-50';
        levelCls = 'text-gray-400';
        msgCls   = 'text-gray-400';
    } else if (l.level === 'error') {
        rowCls   = 'border-b border-gray-50 hover:bg-gray-50';
        levelCls = 'text-red-500';
        msgCls   = 'text-gray-700';
    } else if (l.level === 'warn') {
        rowCls   = 'border-b border-gray-50 hover:bg-gray-50';
        levelCls = 'text-yellow-600';
        msgCls   = 'text-gray-700';
    } else {
        rowCls   = 'border-b border-gray-50 hover:bg-gray-50';
        levelCls = 'text-gray-500';
        msgCls   = 'text-gray-700';
    }
    const time = new Date(l.at).toLocaleTimeString('ko-KR',
        { hour: '2-digit', minute: '2-digit', second: '2-digit' });
    return `<tr class="${rowCls}">
        <td class="py-1.5 px-1 text-gray-400">${time}</td>
        <td class="py-1.5 px-1 font-medium ${levelCls}">${l.level}</td>
        <td class="py-1.5 px-1 text-gray-600">${escHtml(l.code)}</td>
        <td class="py-1.5 px-1 ${msgCls}">${escHtml(l.message)}</td>
    </tr>`;
}

function appendLogRow(log) {
    const tbody = document.getElementById('logsList');
    if (!tbody) return;

    // 빈 상태 메시지 제거
    if (tbody.firstElementChild?.tagName === 'TR' &&
        tbody.firstElementChild.querySelector('td[colspan]')) {
        tbody.innerHTML = '';
    }

    tbody.insertAdjacentHTML('beforeend', buildLogRow(log));

    // 표시 행 수 300개 초과 시 맨 위 행 제거
    while (tbody.children.length > 300) tbody.removeChild(tbody.firstChild);

    // 자동스크롤
    const chk = document.getElementById('autoScrollChk');
    if (chk && chk.checked) scrollLogsToBottom();
}

function setLogFilter(level) {
    logLevelFilter = level;

    const allBtn    = document.getElementById('filterAll');
    const actionBtn = document.getElementById('filterAction');
    if (allBtn && actionBtn) {
        if (level === 'all') {
            allBtn.className    = 'px-3 py-1 rounded-full bg-gray-800 text-white font-medium';
            actionBtn.className = 'px-3 py-1 rounded-full bg-gray-100 text-gray-600 hover:bg-gray-200';
        } else {
            allBtn.className    = 'px-3 py-1 rounded-full bg-gray-100 text-gray-600 hover:bg-gray-200';
            actionBtn.className = 'px-3 py-1 rounded-full bg-gray-800 text-white font-medium';
        }
    }

    // 버퍼에서 필터 적용 후 전체 재렌더
    renderLogsFromBuffer();
}

async function loadLogs() {
    try {
        const res = await fetch('/api/autotrade/logs');
        const logs = await res.json();
        // 서버는 최신순으로 반환 → 뒤집어 오래된 것부터 저장
        localLogs = (logs || []).slice(0, 300).reverse();
        renderLogsFromBuffer();
    } catch (e) {
        console.error('로그 초기 로드 실패:', e);
    }
}

function renderLogsFromBuffer() {
    const tbody = document.getElementById('logsList');
    if (!tbody) return;

    const filtered = logLevelFilter === 'action'
        ? localLogs.filter(l => l.level !== 'debug')
        : localLogs;

    // 최근 300개 표시
    const items = filtered.slice(-300);

    if (items.length === 0) {
        tbody.innerHTML = '<tr><td colspan="4" class="py-4 text-center text-gray-400">로그가 없습니다.</td></tr>';
        return;
    }

    tbody.innerHTML = items.map(l => buildLogRow(l)).join('');
    updateLogTime();
    scrollLogsToBottom();
}

// --- 유틸 ---

function formatMoney(n) {
    if (!n) return '0';
    return n.toLocaleString('ko-KR');
}

function escHtml(str) {
    if (!str) return '';
    return String(str)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}
