#!/usr/bin/env python3
"""Generate HTML report from parsed budget data for 雷震雨."""

import json
import os
import html
from collections import defaultdict

BASE_DIR = "/data/www/files/2026-yjs-lzy"
OUTPUT_HTML = "/data/www/files/2026-yjs-lzy-2026-report.html"
INPUT_JSON = os.path.join(BASE_DIR, "parsed_all.json")

# Load data
with open(INPUT_JSON, 'r', encoding='utf-8') as f:
    data = json.load(f)

matches = data['matches']

# Filter anomalies: amount > 5000万元 = anomaly
ANOMALY_THRESHOLD = 5000

# Build hierarchical structure: city -> county -> unit_type -> keyword -> [matches]
hierarchy = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(list))))

for m in matches:
    city = m['city']
    county = m['county']
    unit_type = m['unit_type']
    keyword = m['keyword']
    hierarchy[city][county][unit_type][keyword].append(m)

# Calculate amounts (filter anomalies)
def get_amount(m):
    """Return amount if valid, 0 if anomaly."""
    if m['amount'] > ANOMALY_THRESHOLD:
        return 0
    return m['amount']

def is_anomaly(m):
    return m['amount'] > ANOMALY_THRESHOLD

# Calculate totals
total_valid_amount = sum(get_amount(m) for m in matches)
total_files = data['total_files']
total_matches = len(matches)
total_cities = len(hierarchy)
total_counties = sum(len(counties) for counties in hierarchy.values())
total_keywords_hit = len(set(m['keyword'] for m in matches))

# Keyword distribution
kw_dist = {}
for m in matches:
    kw = m['keyword']
    if kw not in kw_dist:
        kw_dist[kw] = {'count': 0, 'amount': 0.0, 'anomaly': 0}
    kw_dist[kw]['count'] += 1
    kw_dist[kw]['amount'] += get_amount(m)
    if is_anomaly(m):
        kw_dist[kw]['anomaly'] += 1

# Sort keywords by amount descending
kw_sorted = sorted(kw_dist.items(), key=lambda x: -x[1]['amount'])

# Keyword colors
KW_COLORS = {
    "网络培训": "#e74c3c", "培训": "#3498db", "能力提升": "#2ecc71", "视频拍摄": "#f39c12",
    "党员教育片": "#e67e22", "课程制作": "#1abc9c", "直播": "#e74c3c", "视频": "#9b59b6",
    "课件": "#34495e", "系统": "#16a085", "信息化": "#27ae60", "网络": "#2980b9",
    "数字": "#8e44ad", "设备": "#d35400", "平台": "#c0392b", "维护": "#7f8c8d", "软件": "#2c3e50"
}

# City order
CITY_ORDER = ["成都市", "乐山市", "绵阳市", "攀枝花市", "巴中市", "雅安市"]

# Generate HTML
html_parts = []

# HTML head
html_parts.append(f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2026年 雷震雨 负责市场区域预决算分析报告</title>
<style>
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{
    background: #0d1117;
    color: #c9d1d9;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
    line-height: 1.6;
    padding: 20px;
}}
.container {{ max-width: 1400px; margin: 0 auto; }}

/* Header */
.header {{
    background: linear-gradient(135deg, #1a1f35, #0f1626);
    border: 1px solid #30363d;
    border-radius: 12px;
    padding: 30px;
    margin-bottom: 24px;
    text-align: center;
}}
.header h1 {{
    color: #58a6ff;
    font-size: 28px;
    margin-bottom: 8px;
}}
.header .subtitle {{
    color: #8b949e;
    font-size: 14px;
}}
.header .meta {{
    color: #f0883e;
    font-size: 13px;
    margin-top: 10px;
}}

/* Summary cards */
.summary-grid {{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}}
.summary-card {{
    background: #161b22;
    border: 1px solid #30363d;
    border-radius: 10px;
    padding: 20px;
    text-align: center;
    transition: transform 0.2s;
}}
.summary-card:hover {{ transform: translateY(-3px); border-color: #58a6ff; }}
.summary-card .value {{
    font-size: 32px;
    font-weight: 700;
    color: #58a6ff;
}}
.summary-card .label {{
    color: #8b949e;
    font-size: 13px;
    margin-top: 6px;
}}
.summary-card .unit {{ font-size: 14px; color: #8b949e; }}

/* Keyword chart */
.section-title {{
    color: #58a6ff;
    font-size: 20px;
    margin: 24px 0 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid #30363d;
}}
.kw-chart {{
    background: #161b22;
    border: 1px solid #30363d;
    border-radius: 10px;
    padding: 24px;
    margin-bottom: 24px;
}}
.kw-bar-item {{
    display: flex;
    align-items: center;
    margin-bottom: 12px;
    gap: 12px;
}}
.kw-bar-label {{
    width: 100px;
    text-align: right;
    font-size: 14px;
    color: #c9d1d9;
    flex-shrink: 0;
}}
.kw-bar-track {{
    flex: 1;
    height: 28px;
    background: #21262d;
    border-radius: 6px;
    overflow: hidden;
    position: relative;
}}
.kw-bar-fill {{
    height: 100%;
    border-radius: 6px;
    transition: width 0.8s ease;
    display: flex;
    align-items: center;
    padding-left: 10px;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    min-width: 2px;
}}
.kw-bar-info {{
    width: 200px;
    flex-shrink: 0;
    font-size: 13px;
    color: #8b949e;
}}

/* City navigation */
.city-nav {{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
    margin-bottom: 24px;
}}
.city-nav-card {{
    background: #161b22;
    border: 1px solid #30363d;
    border-radius: 10px;
    padding: 16px;
    cursor: pointer;
    transition: all 0.2s;
    text-align: center;
}}
.city-nav-card:hover {{
    border-color: #58a6ff;
    background: #1a2233;
    transform: translateY(-2px);
}}
.city-nav-card .city-name {{
    font-size: 18px;
    font-weight: 600;
    color: #58a6ff;
}}
.city-nav-card .city-info {{
    color: #8b949e;
    font-size: 12px;
    margin-top: 6px;
}}
.city-nav-card .city-nav-amt {{
    color: #3fb950;
    font-size: 16px;
    font-weight: 600;
    margin-top: 4px;
}}

/* Search */
.search-box {{
    width: 100%;
    padding: 12px 20px;
    background: #161b22;
    border: 1px solid #30363d;
    border-radius: 8px;
    color: #c9d1d9;
    font-size: 14px;
    margin-bottom: 20px;
    outline: none;
}}
.search-box:focus {{ border-color: #58a6ff; }}
.search-box::placeholder {{ color: #484f58; }}

/* City detail */
.city-section {{
    background: #161b22;
    border: 1px solid #30363d;
    border-radius: 10px;
    margin-bottom: 16px;
    overflow: hidden;
}}
.city-header {{
    padding: 16px 20px;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: #1a1f2e;
    transition: background 0.2s;
}}
.city-header:hover {{ background: #1e2436; }}
.city-header .city-title {{
    font-size: 18px;
    font-weight: 600;
    color: #58a6ff;
}}
.city-header .city-summary {{
    color: #8b949e;
    font-size: 13px;
}}
.city-header .toggle {{
    color: #58a6ff;
    font-size: 20px;
    transition: transform 0.3s;
}}
.city-detail {{
    display: none;
    padding: 20px;
}}
.city-detail-title {{
    color: #f0883e;
    font-size: 16px;
    margin-bottom: 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid #30363d;
}}

/* County */
.county-block {{
    background: #0d1117;
    border: 1px solid #30363d;
    border-radius: 8px;
    margin-bottom: 12px;
    overflow: hidden;
}}
.county-header {{
    padding: 12px 16px;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition: background 0.2s;
}}
.county-header:hover {{ background: #161b22; }}
.county-header .county-name {{
    font-size: 15px;
    font-weight: 600;
    color: #c9d1d9;
}}
.county-header .county-summary {{
    color: #3fb950;
    font-size: 13px;
    font-weight: 600;
}}
.county-detail {{ display: none; padding: 16px; }}

/* Unit type */
.unit-block {{
    margin-bottom: 16px;
    border: 1px solid #30363d;
    border-radius: 8px;
    overflow: hidden;
}}
.unit-header {{
    padding: 10px 14px;
    background: #161b22;
    font-size: 14px;
    font-weight: 600;
    display: flex;
    justify-content: space-between;
    align-items: center;
}}
.unit-header .unit-icon {{ margin-right: 6px; }}
.unit-header .unit-summary {{
    color: #3fb950;
    font-size: 13px;
}}
.unit-table-wrap {{ overflow-x: auto; }}

/* Table */
table {{
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}}
th {{
    background: #21262d;
    padding: 10px 12px;
    text-align: left;
    color: #8b949e;
    font-weight: 600;
    white-space: nowrap;
    position: sticky;
    top: 0;
}}
td {{
    padding: 8px 12px;
    border-top: 1px solid #21262d;
    color: #c9d1d9;
    vertical-align: top;
}}
tr:hover td {{ background: #161b22; }}
.kw-tag {{
    display: inline-block;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
}}
.amount-cell {{ color: #3fb950; font-weight: 600; white-space: nowrap; }}
.amount-anomaly {{ color: #666; font-style: italic; }}
.file-link {{
    color: #58a6ff;
    text-decoration: none;
    font-size: 12px;
    display: inline-block;
    margin: 2px 4px 2px 0;
    padding: 2px 8px;
    background: #21262d;
    border-radius: 4px;
    border: 1px solid #30363d;
    transition: all 0.2s;
}}
.file-link:hover {{
    background: #1a2233;
    border-color: #58a6ff;
}}
.content-cell {{
    max-width: 400px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}}
.content-cell:hover {{
    white-space: normal;
    word-break: break-all;
}}

/* Footer */
.footer {{
    text-align: center;
    color: #484f58;
    font-size: 12px;
    margin-top: 30px;
    padding-top: 20px;
    border-top: 1px solid #30363d;
}}

/* Hidden for search */
.hidden {{ display: none !important; }}

/* Responsive */
@media (max-width: 768px) {{
    .summary-grid {{ grid-template-columns: repeat(2, 1fr); }}
    .city-nav {{ grid-template-columns: 1fr; }}
    .content-cell {{ max-width: 150px; }}
}}
</style>
</head>
<body>
<div class="container">

<!-- Header -->
<div class="header">
    <h1>2026年 雷震雨 负责市场区域预决算分析报告</h1>
    <div class="subtitle">基于17个关键字对预算文件进行全量扫描分析 | 自动提取预算金额</div>
    <div class="meta">📅 生成时间：2026年7月22日 | 📁 文件目录：2026-yjs-lzy | 📄 共 {total_files}个预算文件</div>
</div>

<!-- Summary Cards -->
<div class="summary-grid">
    <div class="summary-card">
        <div class="value">{total_files}</div>
        <div class="label">预算文件数</div>
    </div>
    <div class="summary-card">
        <div class="value">{total_matches}</div>
        <div class="label">匹配项总数</div>
    </div>
    <div class="summary-card">
        <div class="value">{total_valid_amount:,.2f}<span class="unit">万元</span></div>
        <div class="label">预算总金额</div>
    </div>
    <div class="summary-card">
        <div class="value">{total_cities}</div>
        <div class="label">覆盖市州</div>
    </div>
    <div class="summary-card">
        <div class="value">{total_counties}</div>
        <div class="label">覆盖区县</div>
    </div>
    <div class="summary-card">
        <div class="value">{total_keywords_hit}/17</div>
        <div class="label">命中关键字</div>
    </div>
</div>

<!-- Keyword Chart -->
<div class="section-title">📊 关键字分布</div>
<div class="kw-chart">
''')

# Keyword bars
max_kw_amount = max((d['amount'] for _, d in kw_sorted if d['amount'] > 0), default=1)
for kw, d in kw_sorted:
    if d['amount'] > 0:
        pct = (d['amount'] / max_kw_amount) * 100
    else:
        pct = 0
    color = KW_COLORS.get(kw, "#58a6ff")
    anomaly_note = f" (含{d['anomaly']}条异常)" if d['anomaly'] > 0 else ""
    html_parts.append(f'''    <div class="kw-bar-item">
        <div class="kw-bar-label">{kw}</div>
        <div class="kw-bar-track">
            <div class="kw-bar-fill" style="width:{pct:.1f}%; background:{color};">{d['count']}次</div>
        </div>
        <div class="kw-bar-info">{d['amount']:,.2f}万元{anomaly_note}</div>
    </div>
''')

html_parts.append('''</div>

<!-- Search -->
<input type="text" class="search-box" id="searchInput" placeholder="🔍 搜索区县、关键字、文件名、匹配内容..." oninput="filterTable()">

<!-- City Navigation -->
<div class="section-title">🗺️ 市州快速导航</div>
<div class="city-nav">
''')

# City nav cards
for city in CITY_ORDER:
    if city not in hierarchy:
        continue
    city_matches = [m for m in matches if m['city'] == city]
    city_amount = sum(get_amount(m) for m in city_matches)
    city_count = len(city_matches)
    city_counties = len(hierarchy[city])
    html_parts.append(f'''    <div class="city-nav-card" onclick="toggleCity('{city}')">
        <div class="city-name">{city}</div>
        <div class="city-info">{city_count}条匹配 | {city_counties}个区县</div>
        <div class="city-nav-amt">{city_amount:,.2f}万元</div>
    </div>
''')

html_parts.append('''</div>

<!-- City Details -->
<div class="section-title">📋 各市州预算明细</div>
''')

# City sections
for city in CITY_ORDER:
    if city not in hierarchy:
        continue
    
    city_matches = [m for m in matches if m['city'] == city]
    city_amount = sum(get_amount(m) for m in city_matches)
    city_count = len(city_matches)
    
    html_parts.append(f'''
<div class="city-section" id="section-{city}">
    <div class="city-header" onclick="toggleCity('{city}')">
        <span class="city-title">{city}</span>
        <span class="city-summary">{city_count}条匹配 | {city_amount:,.2f}万元 | {len(hierarchy[city])}个区县</span>
        <span class="toggle" id="toggle-{city}">▶</span>
    </div>
    <div class="city-detail" id="detail-{city}">
        <div class="city-detail-title">📍 {city} — 预算明细</div>
''')
    
    # County blocks
    counties = sorted(hierarchy[city].keys())
    for county in counties:
        county_matches = [m for m in city_matches if m['county'] == county]
        county_amount = sum(get_amount(m) for m in county_matches)
        county_count = len(county_matches)
        
        html_parts.append(f'''        <div class="county-block" id="county-{city}-{county}">
            <div class="county-header" onclick="toggleCounty(event, '{city}-{county}')">
                <span class="county-name">📍 {county}</span>
                <span><span class="county-summary">{county_amount:,.2f}万元</span> <span style="color:#8b949e;font-size:13px;">| {county_count}条</span></span>
            </div>
            <div class="county-detail" id="county-detail-{city}-{county}">
''')
        
        # Unit type blocks
        unit_types = sorted(hierarchy[city][county].keys())
        for ut in unit_types:
            ut_matches = []
            for kw, kw_matches in hierarchy[city][county][ut].items():
                ut_matches.extend(kw_matches)
            ut_amount = sum(get_amount(m) for m in ut_matches)
            
            icon = "📋" if "组织部" in ut else ("🎓" if "党校" in ut else "🏢")
            
            html_parts.append(f'''                <div class="unit-block">
                    <div class="unit-header">
                        <span><span class="unit-icon">{icon}</span>{ut}</span>
                        <span class="unit-summary">{ut_amount:,.2f}万元</span>
                    </div>
                    <div class="unit-table-wrap">
                        <table>
                            <thead>
                                <tr>
                                    <th>关键字</th>
                                    <th>匹配内容</th>
                                    <th>位置</th>
                                    <th>预算金额</th>
                                    <th>来源文件</th>
                                </tr>
                            </thead>
                            <tbody>
''')
            
            # Keyword rows (merged)
            for kw, kw_matches in sorted(hierarchy[city][county][ut].items(), key=lambda x: -sum(get_amount(m) for m in x[1])):
                kw_amount = sum(get_amount(m) for m in kw_matches)
                kw_count = len(kw_matches)
                color = KW_COLORS.get(kw, "#58a6ff")
                
                # Merge content (first 3 lines)
                contents = list(set(m['content'][:100] for m in kw_matches))[:3]
                merged_content = "<br>".join(html.escape(c) for c in contents)
                if kw_count > 3:
                    merged_content += f"<br><em style='color:#8b949e'>...共{kw_count}条</em>"
                
                # Merge locations (first 5)
                locations = list(set(m['location'] for m in kw_matches))[:5]
                merged_location = ", ".join(html.escape(l) for l in locations)
                if kw_count > 5:
                    merged_location += f" ...+{kw_count-5}"
                
                # Merge file links
                file_links = []
                seen_files = set()
                for m in kw_matches:
                    fname = m['file']
                    if fname not in seen_files:
                        seen_files.add(fname)
                        # Build relative path from HTML location
                        rel_path = m.get('filepath', '')
                        if rel_path.startswith(BASE_DIR + '/'):
                            rel_path = rel_path[len(BASE_DIR)+1:]
                        href = f"2026-yjs-lzy/{rel_path}"
                        file_links.append(f'<a href="{html.escape(href)}" target="_blank" class="file-link">📂 {html.escape(fname)}</a>')
                
                # Amount display
                if kw_amount > 0:
                    amount_display = f'{kw_amount:,.2f}万元'
                    amount_class = 'amount-cell'
                else:
                    # Check if all are anomalies
                    all_anomaly = all(is_anomaly(m) for m in kw_matches)
                    if all_anomaly and any(m['amount'] > 0 for m in kw_matches):
                        amount_display = '—'
                        amount_class = 'amount-anomaly'
                    else:
                        amount_display = '0.00万元'
                        amount_class = 'amount-cell'
                
                # Anomaly note
                anomaly_count = sum(1 for m in kw_matches if is_anomaly(m))
                if anomaly_count > 0 and kw_amount > 0:
                    amount_display += f' <span style="color:#666;font-size:11px">(含{anomaly_count}条异常)</span>'
                
                html_parts.append(f'''                                <tr>
                                    <td><span class="kw-tag" style="background:{color}">{html.escape(kw)}</span> <span style="color:#8b949e;font-size:11px">×{kw_count}</span></td>
                                    <td class="content-cell">{merged_content}</td>
                                    <td style="font-size:12px;color:#8b949e;white-space:nowrap;">{html.escape(merged_location)}</td>
                                    <td class="{amount_class}">{amount_display}</td>
                                    <td>{"".join(file_links)}</td>
                                </tr>
''')
            
            html_parts.append('''                            </tbody>
                        </table>
                    </div>
                </div>
''')
        
        html_parts.append('''            </div>
        </div>
''')
    
    html_parts.append('''    </div>
</div>
''')

# JavaScript
html_parts.append(f'''
<!-- Footer -->
<div class="footer">
    <p>2026年 雷震雨 负责市场区域预决算分析报告</p>
    <p>数据来源：预算文件全量扫描 | 异常金额(>5000万元)已过滤 | 生成日期：2026年7月22日</p>
</div>

</div>

<script>
// Toggle city (accordion mode - close others)
function toggleCity(city) {{
    // Close all other cities
    document.querySelectorAll('.city-detail').forEach(el => {{
        if (el.id !== 'detail-' + city) {{
            el.style.display = 'none';
        }}
    }});
    document.querySelectorAll('.toggle').forEach(el => {{
        if (el.id !== 'toggle-' + city) {{
            el.textContent = '▶';
        }}
    }});
    
    // Toggle current
    const detail = document.getElementById('detail-' + city);
    const toggle = document.getElementById('toggle-' + city);
    if (detail.style.display === 'block') {{
        detail.style.display = 'none';
        toggle.textContent = '▶';
    }} else {{
        detail.style.display = 'block';
        toggle.textContent = '▼';
    }}
}}

// Toggle county
function toggleCounty(event, key) {{
    event.stopPropagation();
    const detail = document.getElementById('county-detail-' + key);
    if (detail.style.display === 'block') {{
        detail.style.display = 'none';
    }} else {{
        detail.style.display = 'block';
    }}
}}

// Search filter
function filterTable() {{
    const query = document.getElementById('searchInput').value.toLowerCase();
    
    document.querySelectorAll('.city-section').forEach(section => {{
        let hasMatch = false;
        
        section.querySelectorAll('.county-block').forEach(county => {{
            let countyHasMatch = false;
            
            county.querySelectorAll('tbody tr').forEach(row => {{
                const text = row.textContent.toLowerCase();
                if (query === '' || text.includes(query)) {{
                    row.classList.remove('hidden');
                    countyHasMatch = true;
                }} else {{
                    row.classList.add('hidden');
                }}
            }});
            
            if (query === '' || countyHasMatch) {{
                county.classList.remove('hidden');
                if (query !== '') {{
                    // Auto-expand
                    const detail = county.querySelector('.county-detail');
                    if (detail) detail.style.display = 'block';
                    const cityDetail = section.querySelector('.city-detail');
                    if (cityDetail) cityDetail.style.display = 'block';
                    const toggle = section.querySelector('.toggle');
                    if (toggle) toggle.textContent = '▼';
                }}
                hasMatch = true;
            }} else {{
                county.classList.add('hidden');
            }}
        }});
        
        if (query === '' || hasMatch) {{
            section.classList.remove('hidden');
        }} else {{
            section.classList.add('hidden');
        }}
    }});
}}
</script>
</body>
</html>
''')

# Write HTML
html_content = ''.join(html_parts)
with open(OUTPUT_HTML, 'w', encoding='utf-8') as f:
    f.write(html_content)

print(f"HTML报告已生成: {OUTPUT_HTML}")
print(f"文件大小: {os.path.getsize(OUTPUT_HTML) / 1024:.1f} KB")
print(f"总文件数: {total_files}")
print(f"总匹配数: {total_matches}")
print(f"有效总金额: {total_valid_amount:,.2f}万元")
print(f"覆盖市州: {total_cities}")
print(f"覆盖区县: {total_counties}")
print(f"命中关键字: {total_keywords_hit}/17")
