#!/usr/bin/env python3
"""
MOPS 重大訊息靜態報告生成器
===========================
從 SQLite 資料庫生成靜態 HTML 報告，可直接在瀏覽器開啟。

使用方式：
    python generate_report.py           # 生成 report.html
    python generate_report.py --open    # 生成並開啟
"""

import sys
sys.stdout.reconfigure(encoding='utf-8')

import sqlite3
import json
from pathlib import Path
from datetime import datetime
import argparse
import webbrowser

# ===== 設定 =====
BASE_DIR = Path(__file__).parent
DB_PATH = BASE_DIR / "data" / "mops_announcements.db"
OUTPUT_PATH = BASE_DIR / "report.html"


def load_data():
    """從資料庫載入資料"""
    if not DB_PATH.exists():
        print(f"錯誤: 資料庫不存在 {DB_PATH}")
        sys.exit(1)

    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row

    # 載入公告
    cursor = conn.execute("""
        SELECT
            id, publish_date, announce_date, announce_time,
            stock_code, company_name, subject, content,
            has_appraiser_info, is_real_estate_related
        FROM announcements
        ORDER BY announce_date DESC, announce_time DESC
    """)
    announcements = [dict(row) for row in cursor.fetchall()]

    # 載入估價師記錄
    cursor = conn.execute("""
        SELECT
            r.*, a.stock_code, a.company_name, a.announce_date
        FROM appraiser_records r
        JOIN announcements a ON r.announcement_id = a.id
    """)
    appraiser_records = [dict(row) for row in cursor.fetchall()]

    # 統計
    cursor = conn.execute("SELECT COUNT(*) FROM announcements")
    total_count = cursor.fetchone()[0]

    cursor = conn.execute("SELECT COUNT(*) FROM announcements WHERE has_appraiser_info = 1")
    appraiser_count = cursor.fetchone()[0]

    cursor = conn.execute("SELECT COUNT(*) FROM announcements WHERE is_real_estate_related = 1")
    real_estate_count = cursor.fetchone()[0]

    cursor = conn.execute("SELECT MIN(announce_date), MAX(announce_date) FROM announcements")
    date_range = cursor.fetchone()

    # 每日統計
    cursor = conn.execute("""
        SELECT
            announce_date,
            COUNT(*) as total,
            SUM(has_appraiser_info) as appraiser,
            SUM(is_real_estate_related) as real_estate
        FROM announcements
        GROUP BY announce_date
        ORDER BY announce_date
    """)
    daily_stats = [dict(row) for row in cursor.fetchall()]

    conn.close()

    return {
        'announcements': announcements,
        'appraiser_records': appraiser_records,
        'stats': {
            'total': total_count,
            'appraiser': appraiser_count,
            'real_estate': real_estate_count,
            'date_min': date_range[0],
            'date_max': date_range[1],
        },
        'daily_stats': daily_stats,
        'generated_at': datetime.now().isoformat(),
    }


def generate_html(data):
    """生成 HTML 內容"""

    html_template = '''<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MOPS 重大訊息瀏覽器</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            background: #f5f5f5;
            color: #333;
            line-height: 1.6;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px 20px;
            margin-bottom: 20px;
            border-radius: 10px;
        }

        header h1 {
            font-size: 2em;
            margin-bottom: 10px;
        }

        header .stats {
            display: flex;
            gap: 30px;
            flex-wrap: wrap;
        }

        header .stat-item {
            text-align: center;
        }

        header .stat-value {
            font-size: 2em;
            font-weight: bold;
        }

        header .stat-label {
            font-size: 0.9em;
            opacity: 0.9;
        }

        .tabs {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }

        .tab-btn {
            padding: 10px 20px;
            border: none;
            background: white;
            border-radius: 8px;
            cursor: pointer;
            font-size: 1em;
            transition: all 0.2s;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .tab-btn:hover {
            background: #667eea;
            color: white;
        }

        .tab-btn.active {
            background: #667eea;
            color: white;
        }

        .tab-content {
            display: none;
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .tab-content.active {
            display: block;
        }

        .filters {
            display: flex;
            gap: 15px;
            margin-bottom: 20px;
            flex-wrap: wrap;
            align-items: center;
        }

        .filters input, .filters select {
            padding: 10px 15px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 1em;
        }

        .filters input[type="text"] {
            min-width: 250px;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 10px;
        }

        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #eee;
        }

        th {
            background: #f8f9fa;
            font-weight: 600;
            position: sticky;
            top: 0;
        }

        tr:hover {
            background: #f8f9fa;
        }

        .tag {
            display: inline-block;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 0.8em;
            margin-right: 5px;
        }

        .tag-appraiser {
            background: #d4edda;
            color: #155724;
        }

        .tag-realestate {
            background: #cce5ff;
            color: #004085;
        }

        .clickable {
            cursor: pointer;
            color: #667eea;
        }

        .clickable:hover {
            text-decoration: underline;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
            z-index: 1000;
            overflow-y: auto;
        }

        .modal.active {
            display: flex;
            justify-content: center;
            align-items: flex-start;
            padding: 50px 20px;
        }

        .modal-content {
            background: white;
            border-radius: 10px;
            max-width: 900px;
            width: 100%;
            max-height: 90vh;
            overflow-y: auto;
            position: relative;
        }

        .modal-header {
            padding: 20px;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: sticky;
            top: 0;
            background: white;
            z-index: 10;
        }

        .modal-body {
            padding: 20px;
        }

        .modal-close {
            font-size: 1.5em;
            cursor: pointer;
            color: #999;
            border: none;
            background: none;
        }

        .modal-close:hover {
            color: #333;
        }

        .detail-grid {
            display: grid;
            grid-template-columns: 1fr 2fr;
            gap: 20px;
        }

        .detail-section h3 {
            margin-bottom: 10px;
            color: #667eea;
        }

        .detail-item {
            margin-bottom: 8px;
        }

        .detail-label {
            font-weight: 600;
            color: #666;
        }

        .content-box {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 6px;
            white-space: pre-wrap;
            font-family: monospace;
            font-size: 0.9em;
            max-height: 400px;
            overflow-y: auto;
        }

        .chart-container {
            height: 300px;
            margin: 20px 0;
        }

        .pagination {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin-top: 20px;
        }

        .pagination button {
            padding: 8px 15px;
            border: 1px solid #ddd;
            background: white;
            border-radius: 4px;
            cursor: pointer;
        }

        .pagination button:hover:not(:disabled) {
            background: #667eea;
            color: white;
            border-color: #667eea;
        }

        .pagination button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .pagination .page-info {
            padding: 8px 15px;
        }

        .appraiser-card {
            background: #f8f9fa;
            border-radius: 8px;
            padding: 15px;
            margin-bottom: 15px;
        }

        .appraiser-card h4 {
            color: #667eea;
            margin-bottom: 10px;
        }

        .info-box {
            background: #e7f3ff;
            border-left: 4px solid #667eea;
            padding: 15px;
            margin-bottom: 20px;
            border-radius: 0 6px 6px 0;
        }

        footer {
            text-align: center;
            padding: 20px;
            color: #666;
            font-size: 0.9em;
        }

        @media (max-width: 768px) {
            .detail-grid {
                grid-template-columns: 1fr;
            }
            .filters input[type="text"] {
                min-width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>📊 MOPS 重大訊息瀏覽器</h1>
            <div class="stats">
                <div class="stat-item">
                    <div class="stat-value" id="stat-total">-</div>
                    <div class="stat-label">總公告數</div>
                </div>
                <div class="stat-item">
                    <div class="stat-value" id="stat-appraiser">-</div>
                    <div class="stat-label">估價師相關</div>
                </div>
                <div class="stat-item">
                    <div class="stat-value" id="stat-realestate">-</div>
                    <div class="stat-label">不動產相關</div>
                </div>
                <div class="stat-item">
                    <div class="stat-value" id="stat-daterange">-</div>
                    <div class="stat-label">資料範圍</div>
                </div>
            </div>
        </header>

        <div class="tabs">
            <button class="tab-btn active" onclick="showTab('list')">📋 公告列表</button>
            <button class="tab-btn" onclick="showTab('appraiser')">🏛 估價師追蹤</button>
            <button class="tab-btn" onclick="showTab('chart')">📈 統計圖表</button>
            <button class="tab-btn" onclick="showTab('raw')">🔍 原始資料</button>
        </div>

        <!-- 公告列表 -->
        <div id="tab-list" class="tab-content active">
            <div class="filters">
                <input type="text" id="search-input" placeholder="🔍 搜尋公司、股票代號、主旨..." oninput="filterList()">
                <select id="type-filter" onchange="filterList()">
                    <option value="all">全部類型</option>
                    <option value="appraiser">估價師相關</option>
                    <option value="realestate">不動產相關</option>
                    <option value="normal">一般公告</option>
                </select>
                <select id="date-filter" onchange="filterList()">
                    <option value="all">全部日期</option>
                </select>
            </div>
            <div id="result-count" style="margin-bottom:10px; color:#666;"></div>
            <table>
                <thead>
                    <tr>
                        <th>日期</th>
                        <th>代號</th>
                        <th>公司</th>
                        <th>主旨</th>
                        <th>類型</th>
                    </tr>
                </thead>
                <tbody id="announcement-list"></tbody>
            </table>
            <div class="pagination">
                <button onclick="prevPage()" id="prev-btn">上一頁</button>
                <span class="page-info" id="page-info">1 / 1</span>
                <button onclick="nextPage()" id="next-btn">下一頁</button>
            </div>
        </div>

        <!-- 估價師追蹤 -->
        <div id="tab-appraiser" class="tab-content">
            <h2>🏛 估價師事務所統計</h2>
            <div class="chart-container">
                <canvas id="appraiser-chart"></canvas>
            </div>
            <h3 style="margin-top:30px;">詳細記錄</h3>
            <div id="appraiser-list"></div>
        </div>

        <!-- 統計圖表 -->
        <div id="tab-chart" class="tab-content">
            <h2>📈 每日公告趨勢</h2>
            <div class="chart-container" style="height:400px;">
                <canvas id="daily-chart"></canvas>
            </div>
            <h2 style="margin-top:30px;">📊 公告類型分佈</h2>
            <div class="chart-container">
                <canvas id="type-chart"></canvas>
            </div>
        </div>

        <!-- 原始資料 -->
        <div id="tab-raw" class="tab-content">
            <div class="info-box">
                此頁面顯示未經處理的原始公告內容，方便檢視資料品質。點擊任一公告查看完整內容。
            </div>
            <div class="filters">
                <select id="raw-type-filter" onchange="filterRaw()">
                    <option value="appraiser">估價師相關</option>
                    <option value="realestate">不動產相關</option>
                    <option value="all">全部公告</option>
                </select>
                <select id="raw-date-filter" onchange="filterRaw()">
                    <option value="all">全部日期</option>
                </select>
            </div>
            <div id="raw-list"></div>
        </div>

        <footer>
            MOPS 重大訊息瀏覽器 | 資料來源：證交所公開資訊觀測站<br>
            報告生成時間：<span id="generated-time"></span>
        </footer>
    </div>

    <!-- 詳情 Modal -->
    <div class="modal" id="detail-modal" onclick="closeModal(event)">
        <div class="modal-content" onclick="event.stopPropagation()">
            <div class="modal-header">
                <h2 id="modal-title">公告詳情</h2>
                <button class="modal-close" onclick="closeModal()">&times;</button>
            </div>
            <div class="modal-body" id="modal-body"></div>
        </div>
    </div>

    <script>
        // 嵌入資料
        const DATA = ''' + json.dumps(data, ensure_ascii=False, indent=2) + ''';

        // 分頁設定
        const PAGE_SIZE = 50;
        let currentPage = 1;
        let filteredData = [];

        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            initStats();
            initDateFilters();
            filterList();
            initCharts();
            initAppraiserList();
            filterRaw();
            document.getElementById('generated-time').textContent = new Date(DATA.generated_at).toLocaleString('zh-TW');
        });

        function initStats() {
            document.getElementById('stat-total').textContent = DATA.stats.total.toLocaleString();
            document.getElementById('stat-appraiser').textContent = DATA.stats.appraiser.toLocaleString();
            document.getElementById('stat-realestate').textContent = DATA.stats.real_estate.toLocaleString();
            document.getElementById('stat-daterange').textContent = `${DATA.stats.date_min} ~ ${DATA.stats.date_max}`;
        }

        function initDateFilters() {
            const dates = [...new Set(DATA.announcements.map(a => a.announce_date))].sort().reverse();
            const options = dates.map(d => `<option value="${d}">${d}</option>`).join('');
            document.getElementById('date-filter').innerHTML = '<option value="all">全部日期</option>' + options;
            document.getElementById('raw-date-filter').innerHTML = '<option value="all">全部日期</option>' + options;
        }

        function showTab(tabId) {
            document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
            document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
            document.getElementById('tab-' + tabId).classList.add('active');
            event.target.classList.add('active');
        }

        function filterList() {
            const search = document.getElementById('search-input').value.toLowerCase();
            const typeFilter = document.getElementById('type-filter').value;
            const dateFilter = document.getElementById('date-filter').value;

            filteredData = DATA.announcements.filter(a => {
                // 搜尋
                if (search && !(
                    a.company_name.toLowerCase().includes(search) ||
                    a.stock_code.toLowerCase().includes(search) ||
                    a.subject.toLowerCase().includes(search)
                )) return false;

                // 類型篩選
                if (typeFilter === 'appraiser' && !a.has_appraiser_info) return false;
                if (typeFilter === 'realestate' && !a.is_real_estate_related) return false;
                if (typeFilter === 'normal' && (a.has_appraiser_info || a.is_real_estate_related)) return false;

                // 日期篩選
                if (dateFilter !== 'all' && a.announce_date !== dateFilter) return false;

                return true;
            });

            currentPage = 1;
            renderList();
        }

        function renderList() {
            const start = (currentPage - 1) * PAGE_SIZE;
            const end = start + PAGE_SIZE;
            const pageData = filteredData.slice(start, end);

            document.getElementById('result-count').textContent = `共 ${filteredData.length} 筆`;

            const html = pageData.map(a => `
                <tr>
                    <td>${a.announce_date}</td>
                    <td>${a.stock_code}</td>
                    <td>${a.company_name}</td>
                    <td class="clickable" onclick="showDetail(${a.id})">${a.subject.substring(0, 60)}${a.subject.length > 60 ? '...' : ''}</td>
                    <td>
                        ${a.has_appraiser_info ? '<span class="tag tag-appraiser">估價師</span>' : ''}
                        ${a.is_real_estate_related ? '<span class="tag tag-realestate">不動產</span>' : ''}
                    </td>
                </tr>
            `).join('');

            document.getElementById('announcement-list').innerHTML = html || '<tr><td colspan="5" style="text-align:center;">無資料</td></tr>';

            // 更新分頁
            const totalPages = Math.ceil(filteredData.length / PAGE_SIZE) || 1;
            document.getElementById('page-info').textContent = `${currentPage} / ${totalPages}`;
            document.getElementById('prev-btn').disabled = currentPage <= 1;
            document.getElementById('next-btn').disabled = currentPage >= totalPages;
        }

        function prevPage() {
            if (currentPage > 1) {
                currentPage--;
                renderList();
            }
        }

        function nextPage() {
            const totalPages = Math.ceil(filteredData.length / PAGE_SIZE);
            if (currentPage < totalPages) {
                currentPage++;
                renderList();
            }
        }

        function showDetail(id) {
            const announcement = DATA.announcements.find(a => a.id === id);
            if (!announcement) return;

            const appraiserRecords = DATA.appraiser_records.filter(r => r.announcement_id === id);

            document.getElementById('modal-title').textContent = `[${announcement.stock_code}] ${announcement.company_name}`;

            let html = `
                <div class="detail-grid">
                    <div class="detail-section">
                        <h3>基本資訊</h3>
                        <div class="detail-item"><span class="detail-label">ID:</span> ${announcement.id}</div>
                        <div class="detail-item"><span class="detail-label">股票代號:</span> ${announcement.stock_code}</div>
                        <div class="detail-item"><span class="detail-label">公司名稱:</span> ${announcement.company_name}</div>
                        <div class="detail-item"><span class="detail-label">出表日期:</span> ${announcement.publish_date}</div>
                        <div class="detail-item"><span class="detail-label">發言日期:</span> ${announcement.announce_date}</div>
                        <div class="detail-item"><span class="detail-label">發言時間:</span> ${announcement.announce_time}</div>
                        <h3 style="margin-top:20px;">分類標記</h3>
                        <div class="detail-item"><span class="detail-label">估價師相關:</span> ${announcement.has_appraiser_info ? '✅ 是' : '❌ 否'}</div>
                        <div class="detail-item"><span class="detail-label">不動產相關:</span> ${announcement.is_real_estate_related ? '✅ 是' : '❌ 否'}</div>
                    </div>
                    <div class="detail-section">
                        <h3>主旨</h3>
                        <div class="content-box" style="max-height:100px;">${announcement.subject}</div>
                        <h3 style="margin-top:20px;">完整說明（原始內容）</h3>
                        <div class="content-box">${announcement.content || '(無)'}</div>
                    </div>
                </div>
            `;

            if (appraiserRecords.length > 0) {
                html += '<h3 style="margin-top:20px;">📊 已解析的估價師資訊</h3>';
                appraiserRecords.forEach(r => {
                    html += `
                        <div class="appraiser-card">
                            <div><strong>事務所:</strong> ${r.appraiser_firm || '(未解析)'}</div>
                            <div><strong>估價師:</strong> ${r.appraiser_names || '(未解析)'}</div>
                            <div><strong>證書字號:</strong> ${r.appraiser_licenses || '(未解析)'}</div>
                            <div><strong>金額:</strong> ${r.appraisal_amount ? r.appraisal_amount.toLocaleString() + ' 元' : '(未解析)'}</div>
                            <div><strong>備註:</strong> ${r.notes || '(無)'}</div>
                        </div>
                    `;
                });
            } else if (announcement.has_appraiser_info) {
                html += '<div class="info-box" style="background:#fff3cd; border-color:#ffc107;">⚠️ 此公告標記為估價師相關，但未成功解析出估價師資訊</div>';
            }

            document.getElementById('modal-body').innerHTML = html;
            document.getElementById('detail-modal').classList.add('active');
        }

        function closeModal(event) {
            if (!event || event.target === document.getElementById('detail-modal')) {
                document.getElementById('detail-modal').classList.remove('active');
            }
        }

        function filterRaw() {
            const typeFilter = document.getElementById('raw-type-filter').value;
            const dateFilter = document.getElementById('raw-date-filter').value;

            let data = DATA.announcements.filter(a => {
                if (typeFilter === 'appraiser' && !a.has_appraiser_info) return false;
                if (typeFilter === 'realestate' && !a.is_real_estate_related) return false;
                if (dateFilter !== 'all' && a.announce_date !== dateFilter) return false;
                return true;
            }).slice(0, 50);

            const html = data.map(a => `
                <div class="appraiser-card" style="cursor:pointer;" onclick="showDetail(${a.id})">
                    <h4>[${a.stock_code}] ${a.company_name}
                        ${a.has_appraiser_info ? '<span class="tag tag-appraiser">估價師</span>' : ''}
                        ${a.is_real_estate_related ? '<span class="tag tag-realestate">不動產</span>' : ''}
                    </h4>
                    <div style="color:#666; margin-bottom:10px;">${a.announce_date} | ${a.subject}</div>
                </div>
            `).join('');

            document.getElementById('raw-list').innerHTML = html || '<p>無資料</p>';
        }

        function initCharts() {
            // 每日趨勢圖
            const dailyCtx = document.getElementById('daily-chart').getContext('2d');
            new Chart(dailyCtx, {
                type: 'line',
                data: {
                    labels: DATA.daily_stats.map(d => d.announce_date),
                    datasets: [
                        {
                            label: '總公告',
                            data: DATA.daily_stats.map(d => d.total),
                            borderColor: '#667eea',
                            tension: 0.1
                        },
                        {
                            label: '估價師相關',
                            data: DATA.daily_stats.map(d => d.appraiser),
                            borderColor: '#28a745',
                            tension: 0.1
                        },
                        {
                            label: '不動產相關',
                            data: DATA.daily_stats.map(d => d.real_estate),
                            borderColor: '#17a2b8',
                            tension: 0.1
                        }
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false
                }
            });

            // 類型分佈圖
            const typeCtx = document.getElementById('type-chart').getContext('2d');
            const appraiserOnly = DATA.stats.appraiser;
            const realEstateOnly = DATA.announcements.filter(a => a.is_real_estate_related && !a.has_appraiser_info).length;
            const normal = DATA.stats.total - appraiserOnly - realEstateOnly;

            new Chart(typeCtx, {
                type: 'doughnut',
                data: {
                    labels: ['估價師相關', '不動產相關（無估價師）', '一般公告'],
                    datasets: [{
                        data: [appraiserOnly, realEstateOnly, normal],
                        backgroundColor: ['#28a745', '#17a2b8', '#6c757d']
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false
                }
            });
        }

        function initAppraiserList() {
            // 統計事務所
            const firmStats = {};
            DATA.appraiser_records.forEach(r => {
                if (r.appraiser_firm) {
                    if (!firmStats[r.appraiser_firm]) {
                        firmStats[r.appraiser_firm] = { count: 0, amount: 0 };
                    }
                    firmStats[r.appraiser_firm].count++;
                    firmStats[r.appraiser_firm].amount += r.appraisal_amount || 0;
                }
            });

            const sorted = Object.entries(firmStats).sort((a, b) => b[1].count - a[1].count);

            // 圖表
            const ctx = document.getElementById('appraiser-chart').getContext('2d');
            new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: sorted.slice(0, 10).map(s => s[0]),
                    datasets: [{
                        label: '案件數',
                        data: sorted.slice(0, 10).map(s => s[1].count),
                        backgroundColor: '#667eea'
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    indexAxis: 'y'
                }
            });

            // 列表
            const html = DATA.appraiser_records.map(r => `
                <div class="appraiser-card" style="cursor:pointer;" onclick="showDetail(${r.announcement_id})">
                    <h4>[${r.stock_code}] ${r.company_name}</h4>
                    <div><strong>事務所:</strong> ${r.appraiser_firm || '(未解析)'}</div>
                    <div><strong>估價師:</strong> ${r.appraiser_names || '(未解析)'}</div>
                    <div><strong>金額:</strong> ${r.appraisal_amount ? r.appraisal_amount.toLocaleString() + ' 元' : '(未解析)'}</div>
                </div>
            `).join('');

            document.getElementById('appraiser-list').innerHTML = html || '<p>無估價師記錄</p>';
        }

        // ESC 關閉 modal
        document.addEventListener('keydown', e => {
            if (e.key === 'Escape') closeModal();
        });
    </script>
</body>
</html>'''

    return html_template


def main():
    parser = argparse.ArgumentParser(description='生成 MOPS 靜態報告')
    parser.add_argument('--open', action='store_true', help='生成後自動開啟')
    args = parser.parse_args()

    print("載入資料...")
    data = load_data()

    print(f"公告數: {data['stats']['total']}")
    print(f"估價師相關: {data['stats']['appraiser']}")

    print("生成 HTML...")
    html = generate_html(data)

    print(f"寫入檔案: {OUTPUT_PATH}")
    OUTPUT_PATH.write_text(html, encoding='utf-8')

    print("✅ 完成！")

    if args.open:
        print("開啟瀏覽器...")
        webbrowser.open(OUTPUT_PATH.as_uri())


if __name__ == "__main__":
    main()
