/**
 * StockChart - TradingView Lightweight Charts 기반 주식 차트
 * 틱(기본) / 일봉 / 1분봉 / 5분봉 전환, 실시간 업데이트 지원
 */

let candleChart  = null;  // 캔들 차트 인스턴스 (lazy)
let candleSeries = null;  // 캔들스틱 시리즈
let maSeries     = {};    // 이동평균선 시리즈 { 5, 20, 60 }
let tickChart    = null;  // 틱 차트 인스턴스
let tickSeries   = null;  // 틱 라인 시리즈
let currentPeriod = 'minute1';

// 틱 데이터 버퍼
const tickBuffer = [];

// 공통 차트 옵션 (autoSize로 컨테이너 크기 자동 추적)
const CHART_BASE_OPTIONS = {
    autoSize: true,
    layout: {
        background: { color: '#ffffff' },
        textColor: '#374151',
    },
    grid: {
        vertLines: { color: '#f3f4f6' },
        horzLines: { color: '#f3f4f6' },
    },
    crosshair: { mode: LightweightCharts.CrosshairMode.Normal },
    rightPriceScale: { borderColor: '#e5e7eb' },
    timeScale: {
        borderColor: '#e5e7eb',
        timeVisible: true,
    },
};

// 틱 차트 초기화
function initTickChart() {
    const container = document.getElementById('tickChartContainer');
    if (!container || tickChart) return;

    tickChart  = LightweightCharts.createChart(container, CHART_BASE_OPTIONS);
    tickSeries = tickChart.addLineSeries({
        color: '#6366f1',
        lineWidth: 2,
        crosshairMarkerVisible: true,
        lastValueVisible: true,
        priceLineVisible: false,
    });

    if (tickBuffer.length > 0) {
        tickSeries.setData([...tickBuffer]);
        tickChart.timeScale().fitContent();
    }
}

// SMA 계산: closes 배열과 period를 받아 [{time, value}] 반환
function calcSMA(candles, period) {
    const result = [];
    for (let i = period - 1; i < candles.length; i++) {
        let sum = 0;
        for (let j = i - period + 1; j <= i; j++) sum += candles[j].close;
        result.push({ time: candles[i].time, value: Math.round(sum / period) });
    }
    return result;
}

// 캔들 차트 lazy 초기화
function ensureCandleChart() {
    if (candleChart) return;
    const container = document.getElementById('chartContainer');
    if (!container) return;

    candleChart  = LightweightCharts.createChart(container, CHART_BASE_OPTIONS);
    candleSeries = candleChart.addCandlestickSeries({
        upColor:         '#ef4444',
        downColor:       '#3b82f6',
        borderUpColor:   '#ef4444',
        borderDownColor: '#3b82f6',
        wickUpColor:     '#ef4444',
        wickDownColor:   '#3b82f6',
    });

    // 이동평균선 시리즈 추가 (20분/60분/120분)
    maSeries[20]  = candleChart.addLineSeries({ color: '#f59e0b', lineWidth: 1, priceLineVisible: false, lastValueVisible: false, crosshairMarkerVisible: false });
    maSeries[60]  = candleChart.addLineSeries({ color: '#10b981', lineWidth: 1, priceLineVisible: false, lastValueVisible: false, crosshairMarkerVisible: false });
    maSeries[120] = candleChart.addLineSeries({ color: '#8b5cf6', lineWidth: 1, priceLineVisible: false, lastValueVisible: false, crosshairMarkerVisible: false });
}

// 캔들 데이터 로딩 + 이동평균선 계산
async function loadChart(period) {
    if (!STOCK_CODE) return;
    const endpoint = period === 'daily'
        ? `/api/stock/${STOCK_CODE}/chart`
        : `/api/stock/${STOCK_CODE}/chart?period=${period}`;
    try {
        const resp = await fetch(endpoint);
        if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
        const candles = await resp.json();
        if (!candles || candles.length === 0) return;

        const data = candles.map(c => ({
            time: c.time, open: c.open, high: c.high, low: c.low, close: c.close,
        }));
        candleSeries.setData(data);

        // 이동평균선 업데이트
        [20, 60, 120].forEach(n => {
            if (maSeries[n]) maSeries[n].setData(calcSMA(data, n));
        });

        candleChart.timeScale().fitContent();
    } catch (err) {
        console.error('차트 데이터 로딩 실패:', err);
    }
}

// 탭 UI 업데이트
function updateTabUI(period) {
    ['daily', 'minute1', 'minute5', 'tick'].forEach(p => {
        const tab = document.getElementById(`tab-${p}`);
        if (!tab) return;
        tab.className = p === period
            ? 'px-4 py-1.5 text-sm rounded-full bg-blue-500 text-white font-medium'
            : 'px-4 py-1.5 text-sm rounded-full bg-gray-100 text-gray-600 font-medium hover:bg-gray-200';
    });
}

// 탭 전환
function switchChart(period) {
    currentPeriod = period;
    updateTabUI(period);

    const candleEl = document.getElementById('chartContainer');
    const tickEl   = document.getElementById('tickChartContainer');

    if (period === 'tick') {
        if (candleEl) candleEl.style.display = 'none';
        if (tickEl)   tickEl.style.display   = 'block';
        if (!tickChart) initTickChart();
        if (tickSeries && tickBuffer.length > 0) {
            tickSeries.setData([...tickBuffer]);
            tickChart.timeScale().fitContent();
        }
    } else {
        if (tickEl)   tickEl.style.display   = 'none';
        if (candleEl) candleEl.style.display = 'block';
        ensureCandleChart();
        loadChart(period);
    }
}

// WebSocket 체결 수신 시 틱 버퍼에 추가
function appendTick(price) {
    if (!price.currentPrice) return;
    const now = Math.floor(Date.now() / 1000);
    const point = { time: now, value: price.currentPrice };

    if (tickBuffer.length > 0 && tickBuffer[tickBuffer.length - 1].time === now) {
        tickBuffer[tickBuffer.length - 1].value = price.currentPrice;
    } else {
        tickBuffer.push(point);
        if (tickBuffer.length > 1000) tickBuffer.shift();
    }

    if (currentPeriod === 'tick' && tickSeries) {
        try { tickSeries.update(point); } catch (_) {}
    }
}

// 실시간 현재가로 마지막 캔들 업데이트
function updateLastCandle(price) {
    if (!candleSeries || !price.currentPrice) return;
    const now = Math.floor(Date.now() / 1000);
    try {
        candleSeries.update({
            time:  now,
            open:  price.open  || price.currentPrice,
            high:  price.high  || price.currentPrice,
            low:   price.low   || price.currentPrice,
            close: price.currentPrice,
        });
    } catch (_) {}
}

// 체결시각 포맷 (HHMMSS → HH:MM:SS)
function formatTradeTime(t) {
    if (!t || t.length < 6) return '-';
    return `${t.slice(0,2)}:${t.slice(2,4)}:${t.slice(4,6)}`;
}

// 거래대금 포맷
function formatTradeMoney(n) {
    if (!n) return '-';
    if (n >= 1000000000000) return (n / 1000000000000).toFixed(2) + '조';
    if (n >= 100000000)     return (n / 100000000).toFixed(1) + '억';
    if (n >= 10000)         return Math.round(n / 10000) + '만';
    return n.toLocaleString('ko-KR');
}

// 현재가 DOM 업데이트
function updatePriceUI(price) {
    const priceEl     = document.getElementById('currentPrice');
    const changeEl    = document.getElementById('changeInfo');
    const updatedAtEl = document.getElementById('updatedAt');
    const highEl      = document.getElementById('highPrice');
    const lowEl       = document.getElementById('lowPrice');
    const volumeEl    = document.getElementById('volume');
    if (!priceEl) return;

    const prevPrice = parseInt(priceEl.dataset.raw || '0');
    const isUp   = price.currentPrice > prevPrice;
    const isDown = price.currentPrice < prevPrice;

    priceEl.textContent = formatNumber(price.currentPrice) + '원';
    priceEl.dataset.raw = price.currentPrice;

    const sign = price.changePrice >= 0 ? '+' : '';
    changeEl.textContent = `${sign}${formatNumber(price.changePrice)}원 (${sign}${price.changeRate.toFixed(2)}%)`;
    changeEl.className = price.changeRate > 0 ? 'text-lg mt-1 text-red-500'
                       : price.changeRate < 0 ? 'text-lg mt-1 text-blue-500'
                       : 'text-lg mt-1 text-gray-500';

    if (highEl)   highEl.textContent   = formatNumber(price.high)   + '원';
    if (lowEl)    lowEl.textContent    = formatNumber(price.low)    + '원';
    if (volumeEl) volumeEl.textContent = formatNumber(price.volume);

    const tradeTimeEl  = document.getElementById('tradeTime');
    if (tradeTimeEl && price.tradeTime)  tradeTimeEl.textContent  = formatTradeTime(price.tradeTime);

    const tradeVolEl   = document.getElementById('tradeVolume');
    if (tradeVolEl && price.tradeVolume) tradeVolEl.textContent   = formatNumber(price.tradeVolume);

    const tradeMoneyEl = document.getElementById('tradeMoney');
    if (tradeMoneyEl)  tradeMoneyEl.textContent  = formatTradeMoney(price.tradeMoney);

    const ask1El = document.getElementById('askPrice1');
    const bid1El = document.getElementById('bidPrice1');
    if (ask1El && price.askPrice1) ask1El.textContent = formatNumber(price.askPrice1) + '원';
    if (bid1El && price.bidPrice1) bid1El.textContent = formatNumber(price.bidPrice1) + '원';

    if (updatedAtEl) {
        const d = new Date(price.updatedAt);
        updatedAtEl.textContent = `${d.getHours()}:${String(d.getMinutes()).padStart(2,'0')}:${String(d.getSeconds()).padStart(2,'0')} 기준`;
    }

    if (isUp) {
        priceEl.classList.remove('flash-down');
        void priceEl.offsetWidth;
        priceEl.classList.add('flash-up');
    } else if (isDown) {
        priceEl.classList.remove('flash-up');
        void priceEl.offsetWidth;
        priceEl.classList.add('flash-down');
    }

    updateLastCandle(price);
    appendTick(price);
}

// 장운영 상태 업데이트
function updateMarketStatus(ms) {
    const el = document.getElementById('marketStatusBadge');
    if (!el) return;
    el.textContent = ms.statusName || '장 중';
    const code = ms.statusCode;
    el.className = 'px-2 py-0.5 rounded text-xs font-medium ';
    if (code === '3')                              el.className += 'bg-green-100 text-green-700';
    else if (['4','8','9'].includes(code))         el.className += 'bg-gray-100 text-gray-600';
    else if (['a','b','c','d'].includes(code))     el.className += 'bg-yellow-100 text-yellow-700';
    else                                           el.className += 'bg-blue-50 text-blue-600';
}

// 종목 메타 업데이트
function updateStockMeta(meta) {
    const upperEl = document.getElementById('upperLimit');
    const lowerEl = document.getElementById('lowerLimit');
    const baseEl  = document.getElementById('basePrice');
    if (upperEl && meta.upperLimit) upperEl.textContent = formatNumber(meta.upperLimit) + '원';
    if (lowerEl && meta.lowerLimit) lowerEl.textContent = formatNumber(meta.lowerLimit) + '원';
    if (baseEl  && meta.basePrice)  baseEl.textContent  = formatNumber(meta.basePrice)  + '원';
}

// 숫자 천 단위 콤마 포맷
function formatNumber(n) {
    return Math.abs(n).toLocaleString('ko-KR');
}

// DOMContentLoaded: WebSocket만 먼저 연결
document.addEventListener('DOMContentLoaded', () => {
    if (typeof STOCK_CODE === 'undefined' || !STOCK_CODE) return;

    stockWS.subscribe(STOCK_CODE);
    stockWS.onPrice(STOCK_CODE, updatePriceUI);
    stockWS.onOrderBook(STOCK_CODE, renderOrderBook);
    stockWS.onProgram(STOCK_CODE, renderProgram);
    stockWS.onMeta(STOCK_CODE, updateStockMeta);
    stockWS.onMarket(updateMarketStatus);

    initOrderBook();
    updateTabUI('minute1');
});

// window.load: 레이아웃 완전 확정 후 차트 초기화
window.addEventListener('load', () => {
    if (typeof STOCK_CODE === 'undefined' || !STOCK_CODE) return;
    // 1분봉 캔들 차트를 기본으로 초기화
    const candleEl = document.getElementById('chartContainer');
    if (candleEl) candleEl.style.display = 'block';
    const tickEl = document.getElementById('tickChartContainer');
    if (tickEl) tickEl.style.display = 'none';
    ensureCandleChart();
    loadChart('minute1');
});
