<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>판매 내역 - 청춘약국 POS</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
    <style>
        :root {
            --bg-primary: #0f172a;
            --bg-secondary: #1e293b;
            --bg-card: #1e293b;
            --bg-card-hover: #334155;
            --border: #334155;
            --text-primary: #f1f5f9;
            --text-secondary: #94a3b8;
            --text-muted: #64748b;
            --accent-teal: #14b8a6;
            --accent-blue: #3b82f6;
            --accent-purple: #a855f7;
            --accent-amber: #f59e0b;
            --accent-emerald: #10b981;
            --accent-rose: #f43f5e;
        }

        * { margin: 0; padding: 0; box-sizing: border-box; }
        
        body {
            font-family: 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
            background: var(--bg-primary);
            color: var(--text-primary);
            -webkit-font-smoothing: antialiased;
            min-height: 100vh;
        }

        /* ══════════════════ 헤더 ══════════════════ */
        .header {
            background: linear-gradient(135deg, #0f766e 0%, #0d9488 50%, #14b8a6 100%);
            padding: 20px 24px;
            position: sticky;
            top: 0;
            z-index: 100;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
        }
        .header-inner {
            max-width: 1600px;
            margin: 0 auto;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .header-left h1 {
            font-size: 22px;
            font-weight: 700;
            letter-spacing: -0.5px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .header-left p {
            font-size: 13px;
            opacity: 0.85;
            margin-top: 4px;
        }
        .header-nav {
            display: flex;
            gap: 8px;
        }
        .header-nav a {
            color: rgba(255,255,255,0.85);
            text-decoration: none;
            font-size: 13px;
            font-weight: 500;
            padding: 8px 14px;
            border-radius: 8px;
            background: rgba(255,255,255,0.1);
            transition: all 0.2s;
        }
        .header-nav a:hover {
            background: rgba(255,255,255,0.2);
            color: #fff;
        }

        /* ══════════════════ 컨텐츠 ══════════════════ */
        .content {
            max-width: 1600px;
            margin: 0 auto;
            padding: 24px;
        }

        /* ══════════════════ 검색 영역 ══════════════════ */
        .search-bar {
            background: var(--bg-card);
            border-radius: 16px;
            padding: 20px 24px;
            margin-bottom: 20px;
            border: 1px solid var(--border);
            display: flex;
            gap: 16px;
            flex-wrap: wrap;
            align-items: flex-end;
        }
        .search-group {
            display: flex;
            flex-direction: column;
            gap: 6px;
        }
        .search-group label {
            font-size: 11px;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }
        .search-group input, .search-group select {
            padding: 10px 14px;
            background: var(--bg-primary);
            border: 1px solid var(--border);
            border-radius: 8px;
            font-size: 14px;
            font-family: inherit;
            color: var(--text-primary);
            min-width: 140px;
            transition: all 0.2s;
        }
        .search-group input:focus, .search-group select:focus {
            outline: none;
            border-color: var(--accent-teal);
            box-shadow: 0 0 0 3px rgba(20, 184, 166, 0.2);
        }
        .search-group input::placeholder { color: var(--text-muted); }
        .search-btn {
            background: linear-gradient(135deg, var(--accent-teal), var(--accent-emerald));
            color: #fff;
            border: none;
            padding: 10px 28px;
            border-radius: 8px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }
        .search-btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(20, 184, 166, 0.4);
        }

        /* ══════════════════ 통계 카드 ══════════════════ */
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(5, 1fr);
            gap: 16px;
            margin-bottom: 24px;
        }
        .stat-card {
            background: var(--bg-card);
            border-radius: 14px;
            padding: 20px;
            border: 1px solid var(--border);
            position: relative;
            overflow: hidden;
        }
        .stat-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 3px;
        }
        .stat-card.teal::before { background: var(--accent-teal); }
        .stat-card.blue::before { background: var(--accent-blue); }
        .stat-card.purple::before { background: var(--accent-purple); }
        .stat-card.amber::before { background: var(--accent-amber); }
        .stat-card.emerald::before { background: var(--accent-emerald); }
        
        .stat-icon {
            font-size: 24px;
            margin-bottom: 12px;
        }
        .stat-value {
            font-size: 28px;
            font-weight: 700;
            letter-spacing: -1px;
            margin-bottom: 4px;
        }
        .stat-card.teal .stat-value { color: var(--accent-teal); }
        .stat-card.blue .stat-value { color: var(--accent-blue); }
        .stat-card.purple .stat-value { color: var(--accent-purple); }
        .stat-card.amber .stat-value { color: var(--accent-amber); }
        .stat-card.emerald .stat-value { color: var(--accent-emerald); }
        
        .stat-label {
            font-size: 12px;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        /* ══════════════════ 뷰 토글 ══════════════════ */
        .view-controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 16px;
        }
        .code-toggle {
            display: flex;
            gap: 4px;
            background: var(--bg-secondary);
            padding: 4px;
            border-radius: 10px;
        }
        .code-toggle button {
            padding: 8px 16px;
            border: none;
            background: transparent;
            color: var(--text-secondary);
            border-radius: 6px;
            font-size: 12px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }
        .code-toggle button.active {
            background: var(--accent-teal);
            color: #fff;
        }
        .code-toggle button:hover:not(.active) {
            color: var(--text-primary);
        }
        .view-mode {
            display: flex;
            gap: 8px;
        }
        .view-btn {
            padding: 8px 12px;
            border: 1px solid var(--border);
            background: var(--bg-card);
            color: var(--text-secondary);
            border-radius: 8px;
            font-size: 14px;
            cursor: pointer;
            transition: all 0.2s;
        }
        .view-btn.active {
            border-color: var(--accent-teal);
            color: var(--accent-teal);
        }

        /* ══════════════════ 거래 카드 (그룹별) ══════════════════ */
        .transactions-container {
            display: flex;
            flex-direction: column;
            gap: 16px;
        }
        .tx-card {
            background: var(--bg-card);
            border-radius: 16px;
            border: 1px solid var(--border);
            overflow: hidden;
            transition: all 0.2s;
        }
        .tx-card:hover {
            border-color: var(--accent-teal);
        }
        .tx-header {
            padding: 16px 20px;
            background: var(--bg-secondary);
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: pointer;
            user-select: none;
        }
        .tx-header:hover {
            background: var(--bg-card-hover);
        }
        .tx-info {
            display: flex;
            align-items: center;
            gap: 20px;
        }
        .tx-id {
            font-family: 'JetBrains Mono', monospace;
            font-size: 14px;
            font-weight: 600;
            color: var(--accent-teal);
        }
        .tx-time {
            font-size: 13px;
            color: var(--text-secondary);
        }
        .tx-customer {
            font-size: 14px;
            font-weight: 500;
            color: var(--text-primary);
            background: var(--bg-primary);
            padding: 4px 12px;
            border-radius: 20px;
        }
        .tx-summary {
            display: flex;
            align-items: center;
            gap: 16px;
        }
        .tx-count {
            font-size: 13px;
            color: var(--text-muted);
        }
        .tx-amount {
            font-size: 18px;
            font-weight: 700;
            color: var(--accent-emerald);
        }
        .tx-toggle {
            font-size: 16px;
            color: var(--text-muted);
            transition: transform 0.3s;
        }
        .tx-card.open .tx-toggle {
            transform: rotate(180deg);
        }

        /* 품목 테이블 */
        .tx-items {
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.3s ease-out;
        }
        .tx-card.open .tx-items {
            max-height: 2000px;
        }
        .items-table {
            width: 100%;
            border-collapse: collapse;
        }
        .items-table th {
            padding: 12px 16px;
            font-size: 11px;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            text-align: left;
            background: rgba(0,0,0,0.2);
            border-bottom: 1px solid var(--border);
        }
        .items-table th:nth-child(4),
        .items-table th:nth-child(5),
        .items-table th:nth-child(6) {
            text-align: right;
        }
        .items-table td {
            padding: 14px 16px;
            font-size: 13px;
            border-bottom: 1px solid rgba(255,255,255,0.05);
            vertical-align: middle;
        }
        .items-table tr:last-child td {
            border-bottom: none;
        }
        .items-table tr:hover {
            background: rgba(255,255,255,0.02);
        }

        /* 제품 셀 */
        .product-cell {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .product-thumb {
            width: 36px;
            height: 36px;
            object-fit: cover;
            border-radius: 6px;
            background: var(--bg-secondary);
            flex-shrink: 0;
            cursor: pointer;
            transition: transform 0.15s, box-shadow 0.15s;
        }
        .product-thumb:hover {
            transform: scale(1.1);
            box-shadow: 0 4px 12px rgba(139,92,246,0.3);
        }
        .product-thumb-placeholder {
            width: 36px;
            height: 36px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: linear-gradient(135deg, #2a2a3e 0%, #1e1e2e 100%);
            border-radius: 6px;
            flex-shrink: 0;
            border: 1px solid rgba(255,255,255,0.05);
            cursor: pointer;
            transition: transform 0.15s, border-color 0.15s;
        }
        .product-thumb-placeholder:hover {
            transform: scale(1.1);
            border-color: var(--accent-purple);
        }
        .product-thumb-placeholder svg {
            width: 18px;
            height: 18px;
            opacity: 0.3;
            fill: #888;
        }

        /* 이미지 교체 모달 */
        .image-modal {
            display: none;
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(0,0,0,0.8);
            z-index: 1000;
            align-items: center;
            justify-content: center;
            backdrop-filter: blur(4px);
        }
        .image-modal.show { display: flex; }
        
        .image-modal-content {
            background: #1a1a3e;
            border-radius: 16px;
            padding: 24px;
            max-width: 450px;
            width: 90%;
            max-height: 90vh;
            overflow-y: auto;
            border: 1px solid rgba(139,92,246,0.3);
        }
        .image-modal-content h3 {
            margin: 0 0 16px 0;
            color: var(--accent-purple);
            font-size: 18px;
        }
        .image-modal-tabs {
            display: flex;
            gap: 8px;
            margin-bottom: 16px;
        }
        .tab-btn {
            flex: 1;
            padding: 10px;
            border: 1px solid rgba(255,255,255,0.1);
            background: transparent;
            color: var(--text-secondary);
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.2s;
        }
        .tab-btn.active {
            background: var(--accent-purple);
            color: white;
            border-color: var(--accent-purple);
        }
        .tab-content { display: none; }
        .tab-content.active { display: block; }
        
        .image-input {
            width: 100%;
            padding: 12px;
            background: var(--bg-secondary);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 8px;
            color: var(--text-primary);
            margin-bottom: 12px;
        }
        .image-input:focus {
            outline: none;
            border-color: var(--accent-purple);
        }
        
        .camera-container {
            position: relative;
            width: 100%;
            aspect-ratio: 1;
            background: #000;
            border-radius: 8px;
            overflow: hidden;
            margin-bottom: 12px;
        }
        .camera-container video,
        .camera-container canvas {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        .camera-guide {
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            pointer-events: none;
        }
        
        .modal-btns {
            display: flex;
            gap: 8px;
            justify-content: flex-end;
        }
        .btn-modal {
            padding: 10px 20px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.2s;
        }
        .btn-modal.secondary {
            background: var(--bg-secondary);
            color: var(--text-primary);
        }
        .btn-modal.primary {
            background: var(--accent-purple);
            color: white;
        }
        .btn-modal:hover {
            transform: translateY(-1px);
        }
        .product-info {
            display: flex;
            flex-direction: column;
            gap: 2px;
            min-width: 0;
        }
        .product-name {
            font-weight: 600;
            color: var(--text-primary);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .product-supplier {
            font-size: 11px;
            color: var(--text-muted);
        }

        /* 코드 뱃지 */
        .code-badge {
            font-family: 'JetBrains Mono', monospace;
            font-size: 11px;
            font-weight: 500;
            padding: 4px 10px;
            border-radius: 6px;
            display: inline-block;
        }
        .code-drug {
            background: rgba(59, 130, 246, 0.2);
            color: #60a5fa;
            border: 1px solid rgba(59, 130, 246, 0.3);
        }
        .code-barcode {
            background: rgba(16, 185, 129, 0.2);
            color: #34d399;
            border: 1px solid rgba(16, 185, 129, 0.3);
        }
        .code-standard {
            background: rgba(245, 158, 11, 0.2);
            color: #fbbf24;
            border: 1px solid rgba(245, 158, 11, 0.3);
        }
        .code-na {
            background: rgba(148, 163, 184, 0.1);
            color: var(--text-muted);
            border: 1px solid rgba(148, 163, 184, 0.2);
        }
        .code-stack {
            display: flex;
            flex-direction: column;
            gap: 4px;
        }

        /* 바코드 시각화 */
        .barcode-visual {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .barcode-bars {
            display: flex;
            gap: 1px;
            align-items: flex-end;
            height: 20px;
        }
        .barcode-bars span {
            width: 2px;
            background: var(--accent-emerald);
            opacity: 0.7;
        }

        /* 숫자 정렬 */
        .items-table td.qty,
        .items-table td.price {
            text-align: right;
            font-family: 'JetBrains Mono', monospace;
            font-weight: 500;
        }
        .items-table td.price.total {
            color: var(--accent-teal);
            font-weight: 600;
        }

        /* ══════════════════ 리스트 뷰 ══════════════════ */
        .list-view {
            display: none;
        }
        .list-view.active {
            display: block;
        }
        .list-table-wrap {
            background: var(--bg-card);
            border-radius: 16px;
            border: 1px solid var(--border);
            overflow: hidden;
        }
        .list-table {
            width: 100%;
            border-collapse: collapse;
        }
        .list-table th {
            padding: 14px 16px;
            font-size: 11px;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            text-align: left;
            background: var(--bg-secondary);
            border-bottom: 1px solid var(--border);
            position: sticky;
            top: 0;
        }
        .list-table td {
            padding: 14px 16px;
            font-size: 13px;
            border-bottom: 1px solid rgba(255,255,255,0.05);
        }
        .list-table tr:hover {
            background: rgba(255,255,255,0.02);
        }

        /* ══════════════════ 로딩/빈 상태 ══════════════════ */
        .loading-state, .empty-state {
            text-align: center;
            padding: 80px 20px;
            color: var(--text-muted);
        }
        .loading-spinner {
            width: 40px;
            height: 40px;
            border: 3px solid var(--border);
            border-top-color: var(--accent-teal);
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin: 0 auto 16px;
        }
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        .empty-icon {
            font-size: 48px;
            margin-bottom: 16px;
        }

        /* ══════════════════ 반응형 ══════════════════ */
        @media (max-width: 1200px) {
            .stats-grid { grid-template-columns: repeat(3, 1fr); }
        }
        @media (max-width: 768px) {
            .stats-grid { grid-template-columns: repeat(2, 1fr); }
            .header-nav { display: none; }
            .search-bar { flex-direction: column; }
            .search-group { width: 100%; }
            .search-group input, .search-group select { width: 100%; }
            .tx-info { flex-wrap: wrap; gap: 8px; }
            .view-controls { flex-direction: column; gap: 12px; }
        }
    </style>
</head>
<body>
    <div class="header">
        <div class="header-inner">
            <div class="header-left">
                <h1>🧾 판매 내역</h1>
                <p>POS 판매 데이터 · 바코드 · 표준코드 조회</p>
            </div>
            <nav class="header-nav">
                <a href="/admin">📊 대시보드</a>
                <a href="/admin/ai-crm">🤖 AI CRM</a>
                <a href="/admin/alimtalk">📨 알림톡</a>
            </nav>
        </div>
    </div>

    <div class="content">
        <!-- 검색 -->
        <div class="search-bar">
            <div class="search-group">
                <label>조회 기간</label>
                <select id="periodSelect">
                    <option value="1">오늘</option>
                    <option value="3" selected>최근 3일</option>
                    <option value="7">최근 7일</option>
                    <option value="30">최근 30일</option>
                </select>
            </div>
            <div class="search-group">
                <label>검색어</label>
                <input type="text" id="searchInput" placeholder="상품명, 코드, 바코드...">
            </div>
            <div class="search-group">
                <label>바코드</label>
                <select id="barcodeFilter">
                    <option value="all">전체</option>
                    <option value="has">있음</option>
                    <option value="none">없음</option>
                </select>
            </div>
            <button class="search-btn" onclick="loadSalesData()">🔍 조회</button>
        </div>

        <!-- 통계 -->
        <div class="stats-grid">
            <div class="stat-card teal">
                <div class="stat-icon">📅</div>
                <div class="stat-value" id="statTxCount">-</div>
                <div class="stat-label">조회 일수</div>
            </div>
            <div class="stat-card blue">
                <div class="stat-icon">📦</div>
                <div class="stat-value" id="statItemCount">-</div>
                <div class="stat-label">총 판매 품목</div>
            </div>
            <div class="stat-card emerald">
                <div class="stat-icon">💰</div>
                <div class="stat-value" id="statAmount">-</div>
                <div class="stat-label">총 매출액</div>
            </div>
            <div class="stat-card purple">
                <div class="stat-icon">📊</div>
                <div class="stat-value" id="statBarcode">-</div>
                <div class="stat-label">바코드 매핑률</div>
            </div>
            <div class="stat-card amber">
                <div class="stat-icon">🏷️</div>
                <div class="stat-value" id="statProducts">-</div>
                <div class="stat-label">고유 상품</div>
            </div>
        </div>

        <!-- 뷰 컨트롤 -->
        <div class="view-controls">
            <div class="code-toggle">
                <button class="active" data-code="drug" onclick="setCodeView('drug')">상품코드</button>
                <button data-code="barcode" onclick="setCodeView('barcode')">바코드</button>
                <button data-code="standard" onclick="setCodeView('standard')">표준코드</button>
                <button data-code="all" onclick="setCodeView('all')">전체</button>
            </div>
            <div class="view-mode">
                <button class="view-btn active" data-view="group" onclick="setViewMode('group')">📁 거래별</button>
                <button class="view-btn" data-view="list" onclick="setViewMode('list')">📋 목록</button>
            </div>
        </div>

        <!-- 거래별 뷰 -->
        <div id="groupView" class="transactions-container">
            <div class="loading-state">
                <div class="loading-spinner"></div>
                <div>데이터 로딩 중...</div>
            </div>
        </div>

        <!-- 리스트 뷰 -->
        <div id="listView" class="list-view">
            <div class="list-table-wrap">
                <table class="list-table">
                    <thead>
                        <tr>
                            <th>판매일</th>
                            <th>상품명</th>
                            <th id="listCodeHeader">상품코드</th>
                            <th style="text-align:center">수량</th>
                            <th style="text-align:right">단가</th>
                            <th style="text-align:right">합계</th>
                        </tr>
                    </thead>
                    <tbody id="listTableBody"></tbody>
                </table>
            </div>
        </div>
    </div>

    <script>
    let rawData = [];  // API에서 받은 원본 데이터
    let groupedData = [];  // 거래별 그룹화된 데이터
    let currentCodeView = 'drug';
    let currentViewMode = 'group';

    // ──────────────── 코드 뷰 전환 ────────────────
    function setCodeView(view) {
        currentCodeView = view;
        document.querySelectorAll('.code-toggle button').forEach(btn => {
            btn.classList.toggle('active', btn.dataset.code === view);
        });
        
        const headers = {
            'drug': '상품코드',
            'barcode': '바코드',
            'standard': '표준코드',
            'all': '코드 정보'
        };
        document.querySelectorAll('#codeHeader, #listCodeHeader').forEach(el => {
            if (el) el.textContent = headers[view];
        });
        
        render();
    }

    // ──────────────── 뷰 모드 전환 ────────────────
    function setViewMode(mode) {
        currentViewMode = mode;
        document.querySelectorAll('.view-btn').forEach(btn => {
            btn.classList.toggle('active', btn.dataset.view === mode);
        });
        document.getElementById('groupView').style.display = mode === 'group' ? 'flex' : 'none';
        document.getElementById('listView').classList.toggle('active', mode === 'list');
    }

    // ──────────────── 코드 렌더링 ────────────────
    function renderCode(item) {
        if (currentCodeView === 'drug') {
            return `<span class="code-badge code-drug">${item.drug_code}</span>`;
        } else if (currentCodeView === 'barcode') {
            if (item.barcode) {
                return `
                    <div class="barcode-visual">
                        <span class="code-badge code-barcode">${item.barcode}</span>
                        ${renderBarcodeBars(item.barcode)}
                    </div>`;
            }
            return `<span class="code-badge code-na">—</span>`;
        } else if (currentCodeView === 'standard') {
            return item.standard_code 
                ? `<span class="code-badge code-standard">${item.standard_code}</span>`
                : `<span class="code-badge code-na">—</span>`;
        } else {
            return `
                <div class="code-stack">
                    <span class="code-badge code-drug">${item.drug_code}</span>
                    ${item.barcode 
                        ? `<span class="code-badge code-barcode">${item.barcode}</span>` 
                        : `<span class="code-badge code-na">바코드 없음</span>`}
                    ${item.standard_code 
                        ? `<span class="code-badge code-standard">${item.standard_code}</span>` 
                        : ''}
                </div>`;
        }
    }

    // 바코드 시각화 바
    function renderBarcodeBars(barcode) {
        const bars = barcode.split('').map(c => {
            const h = 8 + (parseInt(c) || c.charCodeAt(0) % 10) * 1.2;
            return `<span style="height:${h}px"></span>`;
        }).join('');
        return `<div class="barcode-bars">${bars}</div>`;
    }

    // ──────────────── 포맷 ────────────────
    function formatPrice(num) {
        return new Intl.NumberFormat('ko-KR').format(num);
    }

    function formatDateTime(dt) {
        if (!dt) return '-';
        const d = new Date(dt);
        return `${d.getMonth()+1}/${d.getDate()} ${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`;
    }

    function escapeHtml(str) {
        if (!str) return '';
        return str.replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
    }

    // ──────────────── 데이터 그룹화 (날짜별) ────────────────
    function groupByDate(items) {
        const map = new Map();
        items.forEach(item => {
            const key = item.sale_date;
            if (!map.has(key)) {
                map.set(key, {
                    date: item.sale_date,
                    items: [],
                    total: 0
                });
            }
            const group = map.get(key);
            group.items.push(item);
            group.total += item.total_price || 0;
        });
        return Array.from(map.values()).sort((a, b) => 
            b.date.localeCompare(a.date)
        );
    }

    // ──────────────── 렌더링 ────────────────
    function render() {
        renderGroupView();
        renderListView();
    }

    function renderGroupView() {
        const container = document.getElementById('groupView');
        
        if (groupedData.length === 0) {
            container.innerHTML = `
                <div class="empty-state">
                    <div class="empty-icon">📭</div>
                    <div>판매 내역이 없습니다</div>
                </div>`;
            return;
        }

        container.innerHTML = groupedData.map((tx, idx) => `
            <div class="tx-card" id="tx-${idx}">
                <div class="tx-header" onclick="toggleTransaction(${idx})">
                    <div class="tx-info">
                        <span class="tx-id">📅 ${tx.date}</span>
                    </div>
                    <div class="tx-summary">
                        <span class="tx-count">${tx.items.length}개 품목</span>
                        <span class="tx-amount">${formatPrice(tx.total)}원</span>
                        <span class="tx-toggle">▼</span>
                    </div>
                </div>
                <div class="tx-items">
                    <table class="items-table">
                        <thead>
                            <tr>
                                <th style="width:40%">상품명</th>
                                <th id="codeHeader-${idx}">상품코드</th>
                                <th style="text-align:right;width:8%">수량</th>
                                <th style="text-align:right;width:12%">단가</th>
                                <th style="text-align:right;width:12%">합계</th>
                            </tr>
                        </thead>
                        <tbody>
                            ${tx.items.map(item => `
                                <tr>
                                    <td>
                                        <div class="product-cell">
                                            ${item.thumbnail 
                                                ? `<img src="data:image/jpeg;base64,${item.thumbnail}" class="product-thumb" onclick="openImageModal('${item.barcode || ''}', '${item.drug_code || ''}', '${escapeHtml(item.product_name)}')" alt="">`
                                                : `<div class="product-thumb-placeholder" onclick="openImageModal('${item.barcode || ''}', '${item.drug_code || ''}', '${escapeHtml(item.product_name)}')"><svg viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zm-5-7l-3 3.72L9 13l-3 4h12l-4-5z"/></svg></div>`
                                            }
                                            <div class="product-info">
                                                <span class="product-name">${escapeHtml(item.product_name)}</span>
                                                ${item.supplier ? `<span class="product-supplier">${escapeHtml(item.supplier)}</span>` : ''}
                                            </div>
                                        </div>
                                    </td>
                                    <td>${renderCode(item)}</td>
                                    <td class="qty">${item.quantity}</td>
                                    <td class="price">${formatPrice(item.unit_price)}원</td>
                                    <td class="price total">${formatPrice(item.total_price)}원</td>
                                </tr>
                            `).join('')}
                        </tbody>
                    </table>
                </div>
            </div>
        `).join('');
    }

    function renderListView() {
        const tbody = document.getElementById('listTableBody');
        
        if (rawData.length === 0) {
            tbody.innerHTML = `<tr><td colspan="6" class="empty-state">판매 내역이 없습니다</td></tr>`;
            return;
        }

        tbody.innerHTML = rawData.map(item => `
            <tr>
                <td style="color:var(--text-secondary);font-size:12px;">${item.sale_date}</td>
                <td>
                    <div class="product-cell">
                        ${item.thumbnail 
                            ? `<img src="data:image/jpeg;base64,${item.thumbnail}" class="product-thumb" onclick="openImageModal('${item.barcode || ''}', '${item.drug_code || ''}', '${escapeHtml(item.product_name)}')" alt="">`
                            : `<div class="product-thumb-placeholder" onclick="openImageModal('${item.barcode || ''}', '${item.drug_code || ''}', '${escapeHtml(item.product_name)}')"><svg viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zm-5-7l-3 3.72L9 13l-3 4h12l-4-5z"/></svg></div>`
                        }
                        <div class="product-info">
                            <span class="product-name">${escapeHtml(item.product_name)}</span>
                            ${item.supplier ? `<span class="product-supplier">${escapeHtml(item.supplier)}</span>` : ''}
                        </div>
                    </div>
                </td>
                <td>${renderCode(item)}</td>
                <td style="text-align:center">${item.quantity}</td>
                <td style="text-align:right;font-family:'JetBrains Mono',monospace;">${formatPrice(item.unit_price)}원</td>
                <td style="text-align:right;font-family:'JetBrains Mono',monospace;color:var(--accent-teal);font-weight:600;">${formatPrice(item.total_price)}원</td>
            </tr>
        `).join('');
    }

    function toggleTransaction(idx) {
        const card = document.getElementById(`tx-${idx}`);
        card.classList.toggle('open');
    }

    // ──────────────── 데이터 로드 ────────────────
    function loadSalesData() {
        const period = document.getElementById('periodSelect').value;
        const search = document.getElementById('searchInput').value;
        const barcodeFilter = document.getElementById('barcodeFilter').value;

        document.getElementById('groupView').innerHTML = `
            <div class="loading-state">
                <div class="loading-spinner"></div>
                <div>데이터 로딩 중...</div>
            </div>`;

        let url = `/api/sales-detail?days=${period}&barcode=${barcodeFilter}`;
        if (search) url += `&search=${encodeURIComponent(search)}`;

        fetch(url)
            .then(res => res.json())
            .then(data => {
                if (data.success) {
                    rawData = data.items;
                    groupedData = groupByDate(rawData);
                    
                    // 통계 업데이트
                    document.getElementById('statTxCount').textContent = groupedData.length.toLocaleString();
                    document.getElementById('statItemCount').textContent = data.stats.total_count.toLocaleString();
                    document.getElementById('statAmount').textContent = formatPrice(data.stats.total_amount);
                    document.getElementById('statBarcode').textContent = data.stats.barcode_rate + '%';
                    document.getElementById('statProducts').textContent = data.stats.unique_products.toLocaleString();
                    
                    render();
                } else {
                    document.getElementById('groupView').innerHTML = `
                        <div class="empty-state">
                            <div class="empty-icon">⚠️</div>
                            <div>오류: ${data.error}</div>
                        </div>`;
                }
            })
            .catch(err => {
                document.getElementById('groupView').innerHTML = `
                    <div class="empty-state">
                        <div class="empty-icon">❌</div>
                        <div>데이터 로드 실패</div>
                    </div>`;
            });
    }

    // 엔터키 검색
    document.getElementById('searchInput').addEventListener('keypress', e => {
        if (e.key === 'Enter') loadSalesData();
    });

    // 초기 로드
    loadSalesData();

    // ──────────────── 이미지 교체 모달 ────────────────
    let imgModalBarcode = null;
    let imgModalDrugCode = null;
    let imgModalName = null;
    let cameraStream = null;
    let capturedImageData = null;

    function openImageModal(barcode, drugCode, productName) {
        // 바코드나 drug_code 중 하나는 있어야 함
        if (!barcode && !drugCode) {
            showToast('제품 코드 정보가 없습니다', 'error');
            return;
        }
        
        imgModalBarcode = barcode || null;
        imgModalDrugCode = drugCode || null;
        imgModalName = productName || (barcode || drugCode);
        
        document.getElementById('imgModalProductName').textContent = imgModalName;
        document.getElementById('imgModalCode').textContent = barcode || drugCode;
        document.getElementById('imgUrlInput').value = '';
        
        // URL 탭으로 초기화
        switchImageTab('url');
        
        document.getElementById('imageModal').classList.add('show');
        document.getElementById('imgUrlInput').focus();
    }

    function closeImageModal() {
        stopCamera();
        document.getElementById('imageModal').classList.remove('show');
        imgModalBarcode = null;
        imgModalDrugCode = null;
        imgModalName = null;
        capturedImageData = null;
    }

    function switchImageTab(tab) {
        document.querySelectorAll('.image-modal .tab-btn').forEach(btn => {
            btn.classList.toggle('active', btn.dataset.tab === tab);
        });
        document.querySelectorAll('.image-modal .tab-content').forEach(content => {
            content.classList.toggle('active', content.id === 'tab' + tab.charAt(0).toUpperCase() + tab.slice(1));
        });
        
        if (tab === 'camera') {
            startCamera();
        } else {
            stopCamera();
        }
    }

    async function startCamera() {
        try {
            stopCamera();
            
            const constraints = {
                video: {
                    facingMode: { ideal: 'environment' },
                    width: { ideal: 1920 },
                    height: { ideal: 1920 }
                },
                audio: false
            };
            
            cameraStream = await navigator.mediaDevices.getUserMedia(constraints);
            const video = document.getElementById('cameraVideo');
            video.srcObject = cameraStream;
            video.style.display = 'block';
            
            document.getElementById('captureCanvas').style.display = 'none';
            document.getElementById('cameraGuide').style.display = 'block';
            document.getElementById('captureBtn').style.display = 'block';
            document.getElementById('previewBtns').style.display = 'none';
            capturedImageData = null;
            
        } catch (err) {
            console.error('카메라 오류:', err);
            showToast('카메라에 접근할 수 없습니다', 'error');
        }
    }

    function stopCamera() {
        if (cameraStream) {
            cameraStream.getTracks().forEach(track => track.stop());
            cameraStream = null;
        }
        const video = document.getElementById('cameraVideo');
        if (video) video.srcObject = null;
    }

    function capturePhoto() {
        const video = document.getElementById('cameraVideo');
        const canvas = document.getElementById('captureCanvas');
        const ctx = canvas.getContext('2d');
        
        const vw = video.videoWidth;
        const vh = video.videoHeight;
        const minDim = Math.min(vw, vh);
        const cropSize = minDim * 0.8;
        const sx = (vw - cropSize) / 2;
        const sy = (vh - cropSize) / 2;
        
        canvas.width = 800;
        canvas.height = 800;
        ctx.drawImage(video, sx, sy, cropSize, cropSize, 0, 0, 800, 800);
        
        capturedImageData = canvas.toDataURL('image/jpeg', 0.92);
        
        video.style.display = 'none';
        canvas.style.display = 'block';
        document.getElementById('cameraGuide').style.display = 'none';
        document.getElementById('captureBtn').style.display = 'none';
        document.getElementById('previewBtns').style.display = 'flex';
    }

    function retakePhoto() {
        const video = document.getElementById('cameraVideo');
        const canvas = document.getElementById('captureCanvas');
        
        video.style.display = 'block';
        canvas.style.display = 'none';
        document.getElementById('cameraGuide').style.display = 'block';
        document.getElementById('captureBtn').style.display = 'block';
        document.getElementById('previewBtns').style.display = 'none';
        capturedImageData = null;
    }

    async function submitCapturedImage() {
        if (!capturedImageData) {
            showToast('촬영된 이미지가 없습니다', 'error');
            return;
        }
        
        const code = imgModalBarcode || imgModalDrugCode;
        const name = imgModalName;
        const imageData = capturedImageData;
        
        closeImageModal();
        showToast(`"${name}" 이미지 저장 중...`, 'info');
        
        try {
            const res = await fetch(`/api/admin/product-images/${code}/upload`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    image_data: imageData,
                    product_name: name,
                    drug_code: imgModalDrugCode
                })
            });
            const data = await res.json();
            
            if (data.success) {
                showToast('✅ 이미지 저장 완료!', 'success');
                loadSalesData(); // 새로고침
            } else {
                showToast(data.error || '저장 실패', 'error');
            }
        } catch (err) {
            showToast('오류: ' + err.message, 'error');
        }
    }

    async function submitImageUrl() {
        const imageUrl = document.getElementById('imgUrlInput').value.trim();
        
        if (!imageUrl) {
            showToast('이미지 URL을 입력하세요', 'error');
            return;
        }
        
        if (!imageUrl.startsWith('http')) {
            showToast('올바른 URL을 입력하세요', 'error');
            return;
        }
        
        const code = imgModalBarcode || imgModalDrugCode;
        const name = imgModalName;
        
        closeImageModal();
        showToast(`"${name}" 이미지 다운로드 중...`, 'info');
        
        try {
            const res = await fetch(`/api/admin/product-images/${code}/replace`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    image_url: imageUrl,
                    product_name: name,
                    drug_code: imgModalDrugCode
                })
            });
            const data = await res.json();
            
            if (data.success) {
                showToast('✅ 이미지 등록 완료!', 'success');
                loadSalesData(); // 새로고침
            } else {
                showToast(data.error || '등록 실패', 'error');
            }
        } catch (err) {
            showToast('오류: ' + err.message, 'error');
        }
    }

    function showToast(message, type = 'info') {
        const toast = document.createElement('div');
        toast.style.cssText = `
            position: fixed;
            bottom: 24px;
            left: 50%;
            transform: translateX(-50%);
            padding: 12px 24px;
            background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#6366f1'};
            color: white;
            border-radius: 8px;
            font-size: 14px;
            z-index: 2000;
            animation: fadeIn 0.3s;
        `;
        toast.textContent = message;
        document.body.appendChild(toast);
        setTimeout(() => toast.remove(), 3000);
    }

    // 모달 외부 클릭시 닫기
    document.getElementById('imageModal').addEventListener('click', e => {
        if (e.target.id === 'imageModal') closeImageModal();
    });
    </script>

    <!-- 이미지 교체 모달 -->
    <div class="image-modal" id="imageModal">
        <div class="image-modal-content">
            <h3>📷 제품 이미지 등록</h3>
            <div style="background: rgba(139,92,246,0.1); border-radius: 8px; padding: 12px; margin-bottom: 16px;">
                <div style="font-weight: 600;" id="imgModalProductName">제품명</div>
                <div style="font-size: 12px; color: var(--text-muted); font-family: monospace;" id="imgModalCode">코드</div>
            </div>
            
            <div class="image-modal-tabs">
                <button class="tab-btn active" data-tab="url" onclick="switchImageTab('url')">🔗 URL 입력</button>
                <button class="tab-btn" data-tab="camera" onclick="switchImageTab('camera')">📸 촬영</button>
            </div>
            
            <!-- URL 탭 -->
            <div class="tab-content active" id="tabUrl">
                <input type="text" class="image-input" id="imgUrlInput" placeholder="이미지 URL을 입력하세요...">
                <div class="modal-btns">
                    <button class="btn-modal secondary" onclick="closeImageModal()">취소</button>
                    <button class="btn-modal primary" onclick="submitImageUrl()">등록하기</button>
                </div>
            </div>
            
            <!-- 카메라 탭 -->
            <div class="tab-content" id="tabCamera">
                <div class="camera-container">
                    <video id="cameraVideo" autoplay playsinline></video>
                    <canvas id="captureCanvas" style="display:none;"></canvas>
                    <div class="camera-guide" id="cameraGuide">
                        <svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
                            <rect x="10" y="10" width="80" height="80" fill="none" stroke="rgba(139,92,246,0.5)" stroke-width="0.5" stroke-dasharray="2,2"/>
                            <path d="M10,10 L20,10 M10,10 L10,20" fill="none" stroke="#a855f7" stroke-width="1"/>
                            <path d="M90,10 L80,10 M90,10 L90,20" fill="none" stroke="#a855f7" stroke-width="1"/>
                            <path d="M10,90 L20,90 M10,90 L10,80" fill="none" stroke="#a855f7" stroke-width="1"/>
                            <path d="M90,90 L80,90 M90,90 L90,80" fill="none" stroke="#a855f7" stroke-width="1"/>
                        </svg>
                    </div>
                </div>
                <div class="modal-btns" id="captureBtn">
                    <button class="btn-modal secondary" onclick="closeImageModal()">취소</button>
                    <button class="btn-modal primary" onclick="capturePhoto()">📸 촬영</button>
                </div>
                <div class="modal-btns" id="previewBtns" style="display:none;">
                    <button class="btn-modal secondary" onclick="retakePhoto()">다시 촬영</button>
                    <button class="btn-modal primary" onclick="submitCapturedImage()">저장하기</button>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
