#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
任务四: 数据可视化展示 (使用 PyEcharts)
包含折线图、箱线图、散点图、柱状图、对比图及扩展图表
"""

import pandas as pd
import numpy as np
import os
from pyecharts import options as opts
from pyecharts.charts import Line, Bar, Scatter, Pie, Boxplot, Radar, HeatMap, Funnel, Page
from pyecharts.commons.utils import JsCode
import warnings
warnings.filterwarnings('ignore')

print("=" * 80)
print("跨境电商数据分析竞赛 - 任务四:数据可视化 (PyEcharts版)")
print("=" * 80)

# 加载数据
print("\n加载清洗后的数据...")
df = pd.read_csv('../data/ecommerce_sales_cleaned.csv', encoding='utf-8-sig')
df['order_date'] = pd.to_datetime(df['order_date'])
df['product_launch_date'] = pd.to_datetime(df['product_launch_date'])
df['year_month'] = df['order_date'].dt.to_period('M')

print(f"✓ 数据加载完成: {len(df)} 条记录\n")

# 创建输出目录
os.makedirs('../visualization', exist_ok=True)

# ============================================
# 1. 折线图 - 各品类月度销售趋势
# ============================================
print("\n1. 生成折线图 - 各品类月度销售趋势...")

monthly_sales = df.groupby(['year_month', 'category'])['total_amount'].sum().reset_index()
monthly_sales['year_month_str'] = monthly_sales['year_month'].astype(str)

# 获取所有月份和品类
months = sorted(monthly_sales['year_month_str'].unique())
categories = df['category'].unique()

# 创建折线图
line_chart = Line()
line_chart.add_xaxis(months)

for category in categories:
    cat_data = monthly_sales[monthly_sales['category'] == category]
    # 确保所有月份都有数据
    data_dict = dict(zip(cat_data['year_month_str'], cat_data['total_amount']))
    y_data = [round(data_dict.get(m, 0), 2) for m in months]
    
    line_chart.add_yaxis(
        category,
        y_data,
        is_smooth=True,
        label_opts=opts.LabelOpts(is_show=False),
    )

line_chart.set_global_opts(
    title_opts=opts.TitleOpts(title="各品类月度销售额趋势分析", subtitle=""),
    tooltip_opts=opts.TooltipOpts(trigger="axis"),
    xaxis_opts=opts.AxisOpts(
        type_="category",
        name="月份",
        axislabel_opts=opts.LabelOpts(rotate=45)
    ),
    yaxis_opts=opts.AxisOpts(
        type_="value",
        name="销售额 (美元)",
        axislabel_opts=opts.LabelOpts(formatter="{value}")
    ),
    legend_opts=opts.LegendOpts(pos_top="5%"),
    datazoom_opts=[opts.DataZoomOpts(range_start=0, range_end=100)],
)

line_chart.render("../visualization/01_line_charts.html")
print("✓ 已保存: visualization/01_line_charts.html")

# ============================================
# 2. 箱线图 - 价格分布
# ============================================
print("\n2. 生成箱线图 - 价格和配送分布...")

# 各品类产品价格分布
categories_sorted = sorted(df['category'].unique())
price_data = []
for cat in categories_sorted:
    cat_prices = df[df['category'] == cat]['unit_price'].values.tolist()
    price_data.append(cat_prices)

boxplot = Boxplot()
boxplot.add_xaxis(categories_sorted)
boxplot.add_yaxis("价格分布", boxplot.prepare_data(price_data))
boxplot.set_global_opts(
    title_opts=opts.TitleOpts(title="各品类产品价格分布"),
    tooltip_opts=opts.TooltipOpts(trigger="item"),
    xaxis_opts=opts.AxisOpts(
        type_="category",
        name="产品类别",
        axislabel_opts=opts.LabelOpts(rotate=15)
    ),
    yaxis_opts=opts.AxisOpts(
        type_="value",
        name="单价 (美元)"
    ),
)

boxplot.render("../visualization/02_box_plots.html")
print("✓ 已保存: visualization/02_box_plots.html")

# ============================================
# 3. 散点图 - 价格与销量关系
# ============================================
print("\n3. 生成散点图 - 价格/折扣与销量关系...")

# 采样数据以提高性能（可选）
sample_df = df.sample(min(5000, len(df)), random_state=42)

scatter_data = []
for _, row in sample_df.iterrows():
    scatter_data.append([round(row['unit_price'], 2), int(row['quantity'])])

scatter = Scatter()
scatter.add_xaxis([item[0] for item in scatter_data])
scatter.add_yaxis(
    "价格-销量",
    [item[1] for item in scatter_data],
    symbol_size=8,
    label_opts=opts.LabelOpts(is_show=False),
)
scatter.set_global_opts(
    title_opts=opts.TitleOpts(title="产品价格与销售量关系"),
    tooltip_opts=opts.TooltipOpts(formatter="{a} <br/>单价: {c}"),
    xaxis_opts=opts.AxisOpts(
        type_="value",
        name="单价 (美元)",
        splitline_opts=opts.SplitLineOpts(is_show=True)
    ),
    yaxis_opts=opts.AxisOpts(
        type_="value",
        name="销售数量",
        splitline_opts=opts.SplitLineOpts(is_show=True)
    ),
    visualmap_opts=opts.VisualMapOpts(
        type_="color",
        max_=sample_df['quantity'].max(),
        min_=sample_df['quantity'].min(),
        dimension=1,
    ),
)

scatter.render("../visualization/03_scatter_plots.html")
print("✓ 已保存: visualization/03_scatter_plots.html")

# ============================================
# 4. 柱状图 - 销售对比
# ============================================
print("\n4. 生成柱状图 - 销售对比...")

category_sales = df.groupby('category')['total_amount'].sum().sort_values(ascending=False)

bar_chart = (
    Bar()
    .add_xaxis(category_sales.index.tolist())
    .add_yaxis(
        "销售额",
        [round(v, 2) for v in category_sales.values.tolist()],
        label_opts=opts.LabelOpts(
            position="top",
            formatter=JsCode("function(params){return (params.value/1000000).toFixed(2) + 'M';}")
        ),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="各品类销售额对比"),
        tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="shadow"),
        xaxis_opts=opts.AxisOpts(
            name="产品类别",
            axislabel_opts=opts.LabelOpts(rotate=15)
        ),
        yaxis_opts=opts.AxisOpts(
            name="总销售额 (美元)",
            axislabel_opts=opts.LabelOpts(formatter="{value}")
        ),
    )
)

bar_chart.render("../visualization/04_bar_charts.html")
print("✓ 已保存: visualization/04_bar_charts.html")

# ============================================
# 5. 对比图 - 促销vs非促销
# ============================================
print("\n5. 生成对比图 - 促销效果...")

df['has_discount'] = df['discount_rate'] > 0
promo_comparison = df.groupby('has_discount').agg({
    'order_id': 'count',
    'total_amount': 'sum',
    'quantity': 'sum'
}).reset_index()
promo_comparison['has_discount'] = promo_comparison['has_discount'].map({True: '有促销', False: '无促销'})

bar_comparison = (
    Bar()
    .add_xaxis(promo_comparison['has_discount'].tolist())
    .add_yaxis("订单数", promo_comparison['order_id'].tolist())
    .add_yaxis("销售量", promo_comparison['quantity'].tolist())
    .add_yaxis("销售额(万)", [round(v/10000, 2) for v in promo_comparison['total_amount'].tolist()])
    .set_global_opts(
        title_opts=opts.TitleOpts(title="有促销 vs 无促销销售效果对比"),
        tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="shadow"),
        xaxis_opts=opts.AxisOpts(name="促销状态"),
        yaxis_opts=opts.AxisOpts(name="数值"),
        legend_opts=opts.LegendOpts(pos_top="5%"),
    )
)

bar_comparison.render("../visualization/05_comparison_charts.html")
print("✓ 已保存: visualization/05_comparison_charts.html")

# ============================================
# 6. 热力图 - 区域品类销售热力分布
# ============================================
print("\n6. 生成热力图 - 区域品类销售热力分布...")

heatmap_data = df.groupby(['region', 'category'])['total_amount'].sum().reset_index()

regions = sorted(df['region'].unique())
categories_list = sorted(df['category'].unique())

# 准备热力图数据
heat_data = []
for i, region in enumerate(regions):
    for j, category in enumerate(categories_list):
        value = heatmap_data[
            (heatmap_data['region'] == region) & 
            (heatmap_data['category'] == category)
        ]['total_amount'].sum()
        heat_data.append([j, i, round(value, 2)])

heatmap = (
    HeatMap()
    .add_xaxis(categories_list)
    .add_yaxis(
        "销售额",
        regions,
        heat_data,
        label_opts=opts.LabelOpts(is_show=True, position="inside"),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="区域-品类销售热力分布"),
        tooltip_opts=opts.TooltipOpts(trigger="item"),
        visualmap_opts=opts.VisualMapOpts(
            min_=0,
            max_=heatmap_data['total_amount'].max(),
            is_calculable=True,
            orient="horizontal",
            pos_left="center",
            pos_bottom="5%"
        ),
        xaxis_opts=opts.AxisOpts(
            type_="category",
            name="产品类别",
            axislabel_opts=opts.LabelOpts(rotate=15)
        ),
        yaxis_opts=opts.AxisOpts(
            type_="category",
            name="销售区域"
        ),
    )
)

heatmap.render("../visualization/06_heatmaps.html")
print("✓ 已保存: visualization/06_heatmaps.html")

# ============================================
# 7. 饼图 - 销售占比
# ============================================
print("\n7. 生成饼图 - 销售占比...")

category_pct = df.groupby('category')['total_amount'].sum()
pie_data = [(cat, round(val, 2)) for cat, val in category_pct.items()]

pie_chart = (
    Pie()
    .add(
        "销售额",
        pie_data,
        radius=["40%", "70%"],
        label_opts=opts.LabelOpts(formatter="{b}: {d}%"),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="品类销售额占比"),
        legend_opts=opts.LegendOpts(orient="vertical", pos_left="left"),
        tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"),
    )
)

pie_chart.render("../visualization/07_pie_charts.html")
print("✓ 已保存: visualization/07_pie_charts.html")

# ============================================
# 8. 雷达图 - 区域多维度对比
# ============================================
print("\n8. 生成雷达图 - 区域多维度对比...")

region_metrics = df.groupby('region').agg({
    'total_amount': 'sum',
    'quantity': 'sum',
    'order_id': 'count',
    'unit_price': 'mean',
    'delivery_days': 'mean'
}).reset_index()

# 标准化到0-100
for col in region_metrics.columns[1:]:
    max_val = region_metrics[col].max()
    min_val = region_metrics[col].min()
    region_metrics[col] = ((region_metrics[col] - min_val) / (max_val - min_val) * 100).round(2)

schema = [
    opts.RadarIndicatorItem(name="销售额", max_=100),
    opts.RadarIndicatorItem(name="销售量", max_=100),
    opts.RadarIndicatorItem(name="订单数", max_=100),
    opts.RadarIndicatorItem(name="平均单价", max_=100),
    opts.RadarIndicatorItem(name="配送效率", max_=100),
]

radar = Radar()
radar.add_schema(schema=schema)

for _, row in region_metrics.iterrows():
    radar.add(
        row['region'],
        [[
            row['total_amount'],
            row['quantity'],
            row['order_id'],
            row['unit_price'],
            row['delivery_days']
        ]],
        areastyle_opts=opts.AreaStyleOpts(opacity=0.2),
    )

radar.set_global_opts(
    title_opts=opts.TitleOpts(title="不同区域多维度业绩对比雷达图"),
    legend_opts=opts.LegendOpts(),
)

radar.render("../visualization/08_radar_chart.html")
print("✓ 已保存: visualization/08_radar_chart.html")

# ============================================
# 9. 堆叠面积图 - 时间序列占比
# ============================================
print("\n9. 生成堆叠面积图 - 时间序列占比...")

monthly_cat = df.groupby(['year_month', 'category'])['total_amount'].sum().reset_index()
monthly_cat['year_month_str'] = monthly_cat['year_month'].astype(str)

months = sorted(monthly_cat['year_month_str'].unique())
categories = df['category'].unique()

area_line = Line()
area_line.add_xaxis(months)

for category in categories:
    cat_data = monthly_cat[monthly_cat['category'] == category]
    data_dict = dict(zip(cat_data['year_month_str'], cat_data['total_amount']))
    y_data = [round(data_dict.get(m, 0), 2) for m in months]
    
    area_line.add_yaxis(
        category,
        y_data,
        is_smooth=True,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=False),
    )

area_line.set_global_opts(
    title_opts=opts.TitleOpts(title="各品类月度销售额堆叠趋势"),
    tooltip_opts=opts.TooltipOpts(trigger="axis"),
    xaxis_opts=opts.AxisOpts(
        type_="category",
        name="月份",
        boundary_gap=False,
        axislabel_opts=opts.LabelOpts(rotate=45)
    ),
    yaxis_opts=opts.AxisOpts(
        type_="value",
        name="销售额 (美元)"
    ),
    legend_opts=opts.LegendOpts(pos_top="5%"),
)

area_line.render("../visualization/09_area_chart.html")
print("✓ 已保存: visualization/09_area_chart.html")

# ============================================
# 10. 综合Dashboard - 将所有图表整合到一个HTML
# ============================================
print("\n10. 生成综合Dashboard...")

page = Page(layout=Page.SimplePageLayout)
page.add(
    line_chart,
    boxplot,
    scatter,
    bar_chart,
    bar_comparison,
    heatmap,
    pie_chart,
    radar,
    area_line,
)

page.render("../visualization/10_dashboard.html")
print("✓ 已保存: visualization/10_dashboard.html (综合看板)")

print("\n" + "=" * 80)
print("数据可视化任务完成!")
print("=" * 80)
print(f"\n共生成 10 个可视化图表:")
print("  ✓ 折线图: 品类月度趋势")
print("  ✓ 箱线图: 价格分布")
print("  ✓ 散点图: 价格销量关系")
print("  ✓ 柱状图: 销售对比")
print("  ✓ 对比图: 促销效果")
print("  ✓ 热力图: 区域品类分布")
print("  ✓ 饼图: 销售占比")
print("  ✓ 雷达图: 多维度对比")
print("  ✓ 堆叠面积图: 时间序列")
print("  ✓ 综合Dashboard: 所有图表集成")
print(f"\n所有图表已保存至: visualization/ 目录 (HTML交互式格式)")
print("\n提示: 在浏览器中打开 visualization/10_dashboard.html 可查看所有图表")
