#!/usr/bin/env python3
"""
Generate power comparison visualization for P2113 station.
"""
import json
import os
import time

# Power comparison data from API
data = {
  "station_name": "P2113",
  "date": "2025-08-01",
  "comparison_data": [{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 00:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 00:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 00:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 00:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 01:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 01:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 01:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 01:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 02:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 02:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 02:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 02:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 03:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 03:15:00"},{"actual_power":0.0,"diff":35.68,"diff_percent":0,"predicted_power":35.68,"timestamp":"2025-08-01 03:30:00"},{"actual_power":0.0,"diff":123.8,"diff_percent":0,"predicted_power":123.8,"timestamp":"2025-08-01 03:45:00"},{"actual_power":0.0,"diff":160.9,"diff_percent":0,"predicted_power":160.9,"timestamp":"2025-08-01 04:00:00"},{"actual_power":0.0,"diff":251.09,"diff_percent":0,"predicted_power":251.09,"timestamp":"2025-08-01 04:15:00"},{"actual_power":0.0,"diff":330.62,"diff_percent":0,"predicted_power":330.62,"timestamp":"2025-08-01 04:30:00"},{"actual_power":0.0,"diff":395.96,"diff_percent":0,"predicted_power":395.96,"timestamp":"2025-08-01 04:45:00"},{"actual_power":0.0,"diff":439.85,"diff_percent":0,"predicted_power":439.85,"timestamp":"2025-08-01 05:00:00"},{"actual_power":0.0,"diff":488.0,"diff_percent":0,"predicted_power":488.0,"timestamp":"2025-08-01 05:15:00"},{"actual_power":0.0,"diff":501.68,"diff_percent":0,"predicted_power":501.68,"timestamp":"2025-08-01 05:30:00"},{"actual_power":0.0,"diff":541.02,"diff_percent":0,"predicted_power":541.02,"timestamp":"2025-08-01 05:45:00"},{"actual_power":0.0,"diff":555.46,"diff_percent":0,"predicted_power":555.46,"timestamp":"2025-08-01 06:00:00"},{"actual_power":0.0,"diff":563.84,"diff_percent":0,"predicted_power":563.84,"timestamp":"2025-08-01 06:15:00"},{"actual_power":0.0,"diff":565.38,"diff_percent":0,"predicted_power":565.38,"timestamp":"2025-08-01 06:30:00"},{"actual_power":0.0,"diff":615.08,"diff_percent":0,"predicted_power":615.08,"timestamp":"2025-08-01 06:45:00"},{"actual_power":231.6,"diff":402.49,"diff_percent":173.79,"predicted_power":634.09,"timestamp":"2025-08-01 07:00:00"},{"actual_power":265.2,"diff":373.19,"diff_percent":140.72,"predicted_power":638.39,"timestamp":"2025-08-01 07:15:00"},{"actual_power":335.6,"diff":334.57,"diff_percent":99.69,"predicted_power":670.17,"timestamp":"2025-08-01 07:30:00"},{"actual_power":380.4,"diff":295.46,"diff_percent":77.67,"predicted_power":675.86,"timestamp":"2025-08-01 07:45:00"},{"actual_power":420.9,"diff":252.15,"diff_percent":59.91,"predicted_power":673.05,"timestamp":"2025-08-01 08:00:00"},{"actual_power":484.3,"diff":194.2,"diff_percent":40.1,"predicted_power":678.5,"timestamp":"2025-08-01 08:15:00"},{"actual_power":537.5,"diff":161.43,"diff_percent":30.03,"predicted_power":698.93,"timestamp":"2025-08-01 08:30:00"},{"actual_power":571.7,"diff":123.7,"diff_percent":21.64,"predicted_power":695.4,"timestamp":"2025-08-01 08:45:00"},{"actual_power":622.3,"diff":92.03,"diff_percent":14.79,"predicted_power":714.33,"timestamp":"2025-08-01 09:00:00"},{"actual_power":632.5,"diff":40.22,"diff_percent":6.36,"predicted_power":672.72,"timestamp":"2025-08-01 09:15:00"},{"actual_power":655.7,"diff":52.38,"diff_percent":7.99,"predicted_power":708.08,"timestamp":"2025-08-01 09:30:00"},{"actual_power":687.3,"diff":30.09,"diff_percent":4.38,"predicted_power":717.39,"timestamp":"2025-08-01 09:45:00"},{"actual_power":703.9,"diff":-23.46,"diff_percent":-3.33,"predicted_power":680.44,"timestamp":"2025-08-01 10:00:00"},{"actual_power":702.6,"diff":-24.74,"diff_percent":-3.52,"predicted_power":677.86,"timestamp":"2025-08-01 10:15:00"},{"actual_power":706.8,"diff":-24.65,"diff_percent":-3.49,"predicted_power":682.15,"timestamp":"2025-08-01 10:30:00"},{"actual_power":301.0,"diff":341.77,"diff_percent":113.54,"predicted_power":642.77,"timestamp":"2025-08-01 10:45:00"},{"actual_power":754.6,"diff":-170.36,"diff_percent":-22.58,"predicted_power":584.24,"timestamp":"2025-08-01 11:00:00"},{"actual_power":794.4,"diff":-219.13,"diff_percent":-27.58,"predicted_power":575.27,"timestamp":"2025-08-01 11:15:00"},{"actual_power":747.9,"diff":-194.88,"diff_percent":-26.06,"predicted_power":553.02,"timestamp":"2025-08-01 11:30:00"},{"actual_power":698.8,"diff":-168.87,"diff_percent":-24.17,"predicted_power":529.93,"timestamp":"2025-08-01 11:45:00"},{"actual_power":661.9,"diff":-179.64,"diff_percent":-27.14,"predicted_power":482.26,"timestamp":"2025-08-01 12:00:00"},{"actual_power":415.4,"diff":37.09,"diff_percent":8.93,"predicted_power":452.49,"timestamp":"2025-08-01 12:15:00"},{"actual_power":383.9,"diff":-6.8,"diff_percent":-1.77,"predicted_power":377.1,"timestamp":"2025-08-01 12:30:00"},{"actual_power":877.3,"diff":-545.43,"diff_percent":-62.17,"predicted_power":331.87,"timestamp":"2025-08-01 12:45:00"},{"actual_power":720.8,"diff":-441.57,"diff_percent":-61.26,"predicted_power":279.23,"timestamp":"2025-08-01 13:00:00"},{"actual_power":231.2,"diff":5.89,"diff_percent":2.55,"predicted_power":237.09,"timestamp":"2025-08-01 13:15:00"},{"actual_power":725.3,"diff":-525.48,"diff_percent":-72.45,"predicted_power":199.82,"timestamp":"2025-08-01 13:30:00"},{"actual_power":662.0,"diff":-540.54,"diff_percent":-81.65,"predicted_power":121.46,"timestamp":"2025-08-01 13:45:00"},{"actual_power":251.7,"diff":-148.6,"diff_percent":-59.04,"predicted_power":103.1,"timestamp":"2025-08-01 14:00:00"},{"actual_power":670.7,"diff":-599.54,"diff_percent":-89.39,"predicted_power":71.16,"timestamp":"2025-08-01 14:15:00"},{"actual_power":647.7,"diff":-640.68,"diff_percent":-98.92,"predicted_power":7.02,"timestamp":"2025-08-01 14:30:00"},{"actual_power":557.6,"diff":-557.6,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 14:45:00"},{"actual_power":498.7,"diff":-498.7,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 15:00:00"},{"actual_power":539.9,"diff":-539.9,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 15:15:00"},{"actual_power":117.5,"diff":-117.5,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 15:30:00"},{"actual_power":463.7,"diff":-463.7,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 15:45:00"},{"actual_power":466.7,"diff":-466.7,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 16:00:00"},{"actual_power":183.4,"diff":-183.4,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 16:15:00"},{"actual_power":316.1,"diff":-316.1,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 16:30:00"},{"actual_power":207.2,"diff":-207.2,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 16:45:00"},{"actual_power":182.0,"diff":-182.0,"diff_percent":-100.0,"predicted_power":0.0,"timestamp":"2025-08-01 17:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 17:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 17:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 17:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 18:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 18:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 18:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 18:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 19:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 19:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 19:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 19:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 20:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 20:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 20:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 20:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 21:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 21:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 21:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 21:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 22:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 22:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 22:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 22:45:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 23:00:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 23:15:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 23:30:00"},{"actual_power":0.0,"diff":0.0,"diff_percent":0,"predicted_power":0.0,"timestamp":"2025-08-01 23:45:00"}],
  "anomalies": [{"actual_power":231.6,"diff_percent":173.79,"message":"功率差异异常：173.79%","predicted_power":634.09,"timestamp":"2025-08-01 07:00:00"},{"actual_power":265.2,"diff_percent":140.72,"message":"功率差异异常：140.72%","predicted_power":638.39,"timestamp":"2025-08-01 07:15:00"},{"actual_power":335.6,"diff_percent":99.69,"message":"功率差异异常：99.69%","predicted_power":670.17,"timestamp":"2025-08-01 07:30:00"},{"actual_power":380.4,"diff_percent":77.67,"message":"功率差异异常：77.67%","predicted_power":675.86,"timestamp":"2025-08-01 07:45:00"},{"actual_power":420.9,"diff_percent":59.91,"message":"功率差异异常：59.91%","predicted_power":673.05,"timestamp":"2025-08-01 08:00:00"},{"actual_power":484.3,"diff_percent":40.1,"message":"功率差异异常：40.10%","predicted_power":678.5,"timestamp":"2025-08-01 08:15:00"},{"actual_power":537.5,"diff_percent":30.03,"message":"功率差异异常：30.03%","predicted_power":698.93,"timestamp":"2025-08-01 08:30:00"},{"actual_power":571.7,"diff_percent":21.64,"message":"功率差异异常：21.64%","predicted_power":695.4,"timestamp":"2025-08-01 08:45:00"},{"actual_power":301.0,"diff_percent":113.54,"message":"功率差异异常：113.54%","predicted_power":642.77,"timestamp":"2025-08-01 10:45:00"},{"actual_power":754.6,"diff_percent":-22.58,"message":"功率差异异常：-22.58%","predicted_power":584.24,"timestamp":"2025-08-01 11:00:00"},{"actual_power":794.4,"diff_percent":-27.58,"message":"功率差异异常：-27.58%","predicted_power":575.27,"timestamp":"2025-08-01 11:15:00"},{"actual_power":747.9,"diff_percent":-26.06,"message":"功率差异异常：-26.06%","predicted_power":553.02,"timestamp":"2025-08-01 11:30:00"},{"actual_power":698.8,"diff_percent":-24.17,"message":"功率差异异常：-24.17%","predicted_power":529.93,"timestamp":"2025-08-01 11:45:00"},{"actual_power":661.9,"diff_percent":-27.14,"message":"功率差异异常：-27.14%","predicted_power":482.26,"timestamp":"2025-08-01 12:00:00"},{"actual_power":877.3,"diff_percent":-62.17,"message":"功率差异异常：-62.17%","predicted_power":331.87,"timestamp":"2025-08-01 12:45:00"},{"actual_power":720.8,"diff_percent":-61.26,"message":"功率差异异常：-61.26%","predicted_power":279.23,"timestamp":"2025-08-01 13:00:00"},{"actual_power":725.3,"diff_percent":-72.45,"message":"功率差异异常：-72.45%","predicted_power":199.82,"timestamp":"2025-08-01 13:30:00"},{"actual_power":662.0,"diff_percent":-81.65,"message":"功率差异异常：-81.65%","predicted_power":121.46,"timestamp":"2025-08-01 13:45:00"},{"actual_power":251.7,"diff_percent":-59.04,"message":"功率差异异常：-59.04%","predicted_power":103.1,"timestamp":"2025-08-01 14:00:00"},{"actual_power":670.7,"diff_percent":-89.39,"message":"功率差异异常：-89.39%","predicted_power":71.16,"timestamp":"2025-08-01 14:15:00"},{"actual_power":647.7,"diff_percent":-98.92,"message":"功率差异异常：-98.92%","predicted_power":7.02,"timestamp":"2025-08-01 14:30:00"},{"actual_power":557.6,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 14:45:00"},{"actual_power":498.7,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 15:00:00"},{"actual_power":539.9,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 15:15:00"},{"actual_power":117.5,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 15:30:00"},{"actual_power":463.7,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 15:45:00"},{"actual_power":466.7,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 16:00:00"},{"actual_power":183.4,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 16:15:00"},{"actual_power":316.1,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 16:30:00"},{"actual_power":207.2,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 16:45:00"},{"actual_power":182.0,"diff_percent":-100.0,"message":"功率差异异常：-100.00%","predicted_power":0.0,"timestamp":"2025-08-01 17:00:00"}],
  "anomaly_count": 31,
  "total_actual_power": 21015.7,
  "total_predicted_power": 21333.55,
  "total_diff_percent": 1.51
}

# Extract time and power values
times = [d["timestamp"].split(" ")[1][:5] for d in data["comparison_data"]]
actual = [d["actual_power"] for d in data["comparison_data"]]
predicted = [d["predicted_power"] for d in data["comparison_data"]]

# Generate HTML with ECharts
html = f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>P2113 站点功率对比 - 2025 年 8 月 1 日</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 1400px; margin: 0 auto; }}
        .header {{ background: #fff; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }}
        .header h1 {{ margin: 0 0 10px 0; color: #333; }}
        .stats {{ display: flex; gap: 20px; flex-wrap: wrap; }}
        .stat-card {{ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 25px; border-radius: 8px; min-width: 150px; }}
        .stat-card.warning {{ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); }}
        .stat-card.success {{ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); }}
        .stat-value {{ font-size: 24px; font-weight: bold; }}
        .stat-label {{ font-size: 12px; opacity: 0.9; }}
        #chart {{ background: #fff; height: 500px; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }}
        .anomaly-info {{ background: #fff; padding: 20px; border-radius: 8px; margin-top: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }}
        .anomaly-info h3 {{ margin-top: 0; color: #f5576c; }}
        .anomaly-list {{ max-height: 300px; overflow-y: auto; }}
        .anomaly-item {{ padding: 8px; border-bottom: 1px solid #eee; font-size: 13px; }}
        .anomaly-item:last-child {{ border-bottom: none; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📊 P2113 站点功率对比分析</h1>
            <p>日期：2025 年 8 月 1 日 | 数据点数：{len(data["comparison_data"])}</p>
            <div class="stats">
                <div class="stat-card">
                    <div class="stat-value">{data["total_actual_power"]:,.1f}</div>
                    <div class="stat-label">实际总功率 (kW)</div>
                </div>
                <div class="stat-card">
                    <div class="stat-value">{data["total_predicted_power"]:,.1f}</div>
                    <div class="stat-label">预测总功率 (kW)</div>
                </div>
                <div class="stat-card {"warning" if abs(data["total_diff_percent"]) > 5 else "success"}">
                    <div class="stat-value">{data["total_diff_percent"]:+.2f}%</div>
                    <div class="stat-label">总功率差异率</div>
                </div>
                <div class="stat-card warning">
                    <div class="stat-value">{data["anomaly_count"]}</div>
                    <div class="stat-label">异常点数</div>
                </div>
            </div>
        </div>
        <div id="chart"></div>
        <div class="anomaly-info">
            <h3>⚠️ 功率差异异常详情 (共 {data["anomaly_count"]} 处)</h3>
            <div class="anomaly-list">
                {"".join([f'<div class="anomaly-item"><b>{a["timestamp"]}</b> - 实际：{a["actual_power"]:.1f}kW, 预测：{a["predicted_power"]:.1f}kW, 差异：{a["diff_percent"]:+.2f}%</div>' for a in data["anomalies"][:20]])}
                {f'<div class="anomaly-item">... 还有 {data["anomaly_count"] - 20} 处异常</div>' if data["anomaly_count"] > 20 else ''}
            </div>
        </div>
    </div>
    <script>
        var chart = echarts.init(document.getElementById('chart'));
        var option = {{
            title: {{ text: '实际功率 vs 预测功率', left: 'center' }},
            tooltip: {{ trigger: 'axis', axisPointer: {{ type: 'cross' }} }},
            legend: {{ data: ['实际功率', '预测功率'], top: 50 }},
            grid: {{ left: '3%', right: '4%', bottom: '3%', top: 100, containLabel: true }},
            xAxis: {{ 
                type: 'category', 
                data: {json.dumps(times)},
                axisLabel: {{ interval: 15, rotate: 45 }}
            }},
            yAxis: {{ type: 'value', name: '功率 (kW)' }},
            dataZoom: [{{ type: 'slider', start: 0, end: 100 }}, {{ type: 'inside', start: 0, end: 100 }}],
            series: [
                {{
                    name: '实际功率',
                    type: 'line',
                    smooth: true,
                    data: {json.dumps(actual)},
                    itemStyle: {{ color: '#5470c6' }},
                    areaStyle: {{ opacity: 0.3 }}
                }},
                {{
                    name: '预测功率',
                    type: 'line',
                    smooth: true,
                    data: {json.dumps(predicted)},
                    itemStyle: {{ color: '#91cc75' }},
                    lineStyle: {{ type: 'dashed' }}
                }}
            ]
        }};
        chart.setOption(option);
        window.addEventListener('resize', () => chart.resize());
    </script>
</body>
</html>'''

# Save to output directory
output_dir = "/workspace/skills/report-generator/output"
os.makedirs(output_dir, exist_ok=True)
timestamp = int(time.time())
output_path = os.path.join(output_dir, f"p2113_power_comparison_{timestamp}.html")

with open(output_path, 'w', encoding='utf-8') as f:
    f.write(html)

print(json.dumps({
    "status": "success",
    "message": "功率对比图表已生成",
    "file": output_path,
    "address": f"/skill/report-generator/output/p2113_power_comparison_{timestamp}.html",
    "summary": f"P2113 站点 2025 年 8 月 1 日功率对比完成。实际总功率{data['total_actual_power']:,.1f}kW，预测总功率{data['total_predicted_power']:,.1f}kW，总差异率{data['total_diff_percent']:+.2f}%。检测到{data['anomaly_count']}处功率差异异常，主要集中在早晨 (07:00-08:45) 和下午 (10:45-17:00) 时段，可能存在设备问题或天气因素影响。"
}, ensure_ascii=False))
