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

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Rectangle
import warnings
warnings.filterwarnings('ignore')

# 设置中文显示和样式
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")
sns.set_palette("husl")

print("=" * 80)
print("跨境电商数据分析竞赛 - 任务四:数据可视化")
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")

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

# ============================================
# 一、必选可视化图表
# ============================================

print("=" * 80)
print("【必选图表】")
print("=" * 80)

# 1. 折线图 - 各品类月度销售趋势
print("\n1. 生成折线图 - 各品类月度销售趋势...")
fig, axes = plt.subplots(2, 1, figsize=(14, 10))

# 1.1 各品类月度销售额趋势
monthly_sales = df.groupby(['year_month', 'category'])['total_amount'].sum().reset_index()
monthly_sales['year_month_str'] = monthly_sales['year_month'].astype(str)

for category in df['category'].unique():
    cat_data = monthly_sales[monthly_sales['category'] == category]
    axes[0].plot(cat_data['year_month_str'], cat_data['total_amount'], 
                marker='o', label=category, linewidth=2)

axes[0].set_xlabel('月份', fontsize=12)
axes[0].set_ylabel('销售额 (美元)', fontsize=12)
axes[0].set_title('各品类月度销售额趋势分析', fontsize=14, fontweight='bold')
axes[0].legend(title='产品类别', loc='upper left')
axes[0].tick_params(axis='x', rotation=45)
axes[0].grid(True, alpha=0.3)

# 1.2 各区域销售额趋势
monthly_region = df.groupby(['year_month', 'region'])['total_amount'].sum().reset_index()
monthly_region['year_month_str'] = monthly_region['year_month'].astype(str)

for region in df['region'].unique():
    reg_data = monthly_region[monthly_region['region'] == region]
    axes[1].plot(reg_data['year_month_str'], reg_data['total_amount'], 
                marker='s', label=region, linewidth=2)

axes[1].set_xlabel('月份', fontsize=12)
axes[1].set_ylabel('销售额 (美元)', fontsize=12)
axes[1].set_title('各区域销售额随时间变化趋势', fontsize=14, fontweight='bold')
axes[1].legend(title='销售区域', loc='upper left')
axes[1].tick_params(axis='x', rotation=45)
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('../visualization/01_line_charts.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/01_line_charts.png")
plt.close()

# 2. 箱线图 - 价格和配送分布
print("\n2. 生成箱线图 - 价格和配送分布...")
fig, axes = plt.subplots(1, 3, figsize=(18, 6))

# 2.1 各品类产品价格分布
axes[0].boxplot([df[df['category']==cat]['unit_price'].values 
                  for cat in sorted(df['category'].unique())],
                labels=sorted(df['category'].unique()))
axes[0].set_xlabel('产品类别', fontsize=12)
axes[0].set_ylabel('单价 (美元)', fontsize=12)
axes[0].set_title('各品类产品价格分布', fontsize=14, fontweight='bold')
axes[0].tick_params(axis='x', rotation=15)
axes[0].grid(True, alpha=0.3)

# 2.2 各区域配送天数分布
axes[1].boxplot([df[df['region']==reg]['delivery_days'].values 
                  for reg in sorted(df['region'].unique())],
                labels=sorted(df['region'].unique()))
axes[1].set_xlabel('销售区域', fontsize=12)
axes[1].set_ylabel('配送天数', fontsize=12)
axes[1].set_title('各区域配送天数分布', fontsize=14, fontweight='bold')
axes[1].grid(True, alpha=0.3)

# 2.3 不同折扣区间的订单金额分布
df['discount_level'] = pd.cut(df['discount_rate'], 
                              bins=[-0.01, 0, 0.1, 0.2, 1],
                              labels=['无折扣', '小折扣', '中折扣', '大折扣'])
axes[2].boxplot([df[df['discount_level']==level]['total_amount'].values 
                  for level in ['无折扣', '小折扣', '中折扣', '大折扣']],
                labels=['无折扣', '小折扣', '中折扣', '大折扣'])
axes[2].set_xlabel('折扣区间', fontsize=12)
axes[2].set_ylabel('订单金额 (美元)', fontsize=12)
axes[2].set_title('不同折扣区间的订单金额分布', fontsize=14, fontweight='bold')
axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('../visualization/02_box_plots.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/02_box_plots.png")
plt.close()

# 3. 散点图 - 价格/折扣与销量关系
print("\n3. 生成散点图 - 价格/折扣与销量关系...")
fig, axes = plt.subplots(2, 2, figsize=(14, 12))

# 3.1 产品价格与销售量
axes[0,0].scatter(df['unit_price'], df['quantity'], alpha=0.5, s=30)
z = np.polyfit(df['unit_price'], df['quantity'], 1)
p = np.poly1d(z)
axes[0,0].plot(df['unit_price'].sort_values(), 
               p(df['unit_price'].sort_values()), 
               "r--", linewidth=2, label='拟合线')
axes[0,0].set_xlabel('单价 (美元)', fontsize=12)
axes[0,0].set_ylabel('销售数量', fontsize=12)
axes[0,0].set_title('产品价格与销售量关系', fontsize=14, fontweight='bold')
axes[0,0].legend()
axes[0,0].grid(True, alpha=0.3)

# 3.2 折扣率与销售额
axes[0,1].scatter(df['discount_rate'], df['total_amount'], alpha=0.5, s=30, c='orange')
z = np.polyfit(df['discount_rate'], df['total_amount'], 1)
p = np.poly1d(z)
axes[0,1].plot(df['discount_rate'].sort_values(), 
               p(df['discount_rate'].sort_values()), 
               "r--", linewidth=2, label='拟合线')
axes[0,1].set_xlabel('折扣率', fontsize=12)
axes[0,1].set_ylabel('订单金额 (美元)', fontsize=12)
axes[0,1].set_title('折扣率与销售额关系', fontsize=14, fontweight='bold')
axes[0,1].legend()
axes[0,1].grid(True, alpha=0.3)

# 3.3 库存量与销售量
product_sales = df.groupby('product_id').agg({
    'stock_quantity': 'mean',
    'quantity': 'sum'
}).reset_index()
axes[1,0].scatter(product_sales['stock_quantity'], product_sales['quantity'], 
                  alpha=0.6, s=50, c='green')
axes[1,0].set_xlabel('平均库存量', fontsize=12)
axes[1,0].set_ylabel('总销售量', fontsize=12)
axes[1,0].set_title('库存量与销售量关系', fontsize=14, fontweight='bold')
axes[1,0].grid(True, alpha=0.3)

# 3.4 按类别的价格-销量散点
for category in df['category'].unique():
    cat_data = df[df['category'] == category]
    axes[1,1].scatter(cat_data['unit_price'], cat_data['total_amount'], 
                     label=category, alpha=0.6, s=40)
axes[1,1].set_xlabel('单价 (美元)', fontsize=12)
axes[1,1].set_ylabel('订单金额 (美元)', fontsize=12)
axes[1,1].set_title('各品类价格-销售额分布', fontsize=14, fontweight='bold')
axes[1,1].legend(title='产品类别')
axes[1,1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('../visualization/03_scatter_plots.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/03_scatter_plots.png")
plt.close()

# 4. 柱状图 - 销售对比
print("\n4. 生成柱状图 - 销售对比...")
fig, axes = plt.subplots(2, 2, figsize=(16, 12))

# 4.1 各品类销售额对比
category_sales = df.groupby('category')['total_amount'].sum().sort_values(ascending=False)
axes[0,0].bar(range(len(category_sales)), category_sales.values, color=sns.color_palette("husl", len(category_sales)))
axes[0,0].set_xticks(range(len(category_sales)))
axes[0,0].set_xticklabels(category_sales.index, rotation=15)
axes[0,0].set_xlabel('产品类别', fontsize=12)
axes[0,0].set_ylabel('总销售额 (美元)', fontsize=12)
axes[0,0].set_title('各品类销售额对比', fontsize=14, fontweight='bold')
for i, v in enumerate(category_sales.values):
    axes[0,0].text(i, v, f'{v:,.0f}', ha='center', va='bottom', fontsize=10)
axes[0,0].grid(True, alpha=0.3, axis='y')

# 4.2 各区域销售量对比
region_qty = df.groupby('region')['quantity'].sum().sort_values(ascending=False)
axes[0,1].bar(range(len(region_qty)), region_qty.values, color=sns.color_palette("Set2", len(region_qty)))
axes[0,1].set_xticks(range(len(region_qty)))
axes[0,1].set_xticklabels(region_qty.index)
axes[0,1].set_xlabel('销售区域', fontsize=12)
axes[0,1].set_ylabel('总销售量', fontsize=12)
axes[0,1].set_title('各区域销售量对比', fontsize=14, fontweight='bold')
for i, v in enumerate(region_qty.values):
    axes[0,1].text(i, v, f'{v:,.0f}', ha='center', va='bottom', fontsize=10)
axes[0,1].grid(True, alpha=0.3, axis='y')

# 4.3 Top20畅销产品
product_sales = df.groupby('product_name')['total_amount'].sum().sort_values(ascending=False).head(20)
axes[1,0].barh(range(len(product_sales)), product_sales.values)
axes[1,0].set_yticks(range(len(product_sales)))
axes[1,0].set_yticklabels([name[:30] for name in product_sales.index], fontsize=9)
axes[1,0].set_xlabel('总销售额 (美元)', fontsize=12)
axes[1,0].set_title('Top20畅销产品排名', fontsize=14, fontweight='bold')
axes[1,0].invert_yaxis()
axes[1,0].grid(True, alpha=0.3, axis='x')

# 4.4 各国家销售额排名
country_sales = df.groupby('country')['total_amount'].sum().sort_values(ascending=False)
axes[1,1].barh(range(len(country_sales)), country_sales.values, 
               color=sns.color_palette("Spectral", len(country_sales)))
axes[1,1].set_yticks(range(len(country_sales)))
axes[1,1].set_yticklabels(country_sales.index, fontsize=10)
axes[1,1].set_xlabel('总销售额 (美元)', fontsize=12)
axes[1,1].set_title('各国家销售额排名', fontsize=14, fontweight='bold')
axes[1,1].invert_yaxis()
axes[1,1].grid(True, alpha=0.3, axis='x')

plt.tight_layout()
plt.savefig('../visualization/04_bar_charts.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/04_bar_charts.png")
plt.close()

# 5. 对比图
print("\n5. 生成对比图...")
fig, axes = plt.subplots(2, 2, figsize=(16, 12))

# 5.1 各区域各品类销售占比堆叠图
pivot_data = df.groupby(['region', 'category'])['total_amount'].sum().unstack()
pivot_data.plot(kind='bar', stacked=True, ax=axes[0,0], width=0.7)
axes[0,0].set_xlabel('销售区域', fontsize=12)
axes[0,0].set_ylabel('销售额 (美元)', fontsize=12)
axes[0,0].set_title('各区域各品类销售占比对比', fontsize=14, fontweight='bold')
axes[0,0].legend(title='产品类别', bbox_to_anchor=(1.05, 1))
axes[0,0].tick_params(axis='x', rotation=0)

# 5.2 季度销售对比
df['quarter'] = df['order_date'].dt.to_period('Q')
quarter_sales = df.groupby('quarter')['total_amount'].sum()
quarter_sales.plot(kind='bar', ax=axes[0,1], color='skyblue', width=0.7)
axes[0,1].set_xlabel('季度', fontsize=12)
axes[0,1].set_ylabel('销售额 (美元)', fontsize=12)
axes[0,1].set_title('不同季度销售业绩对比', fontsize=14, fontweight='bold')
axes[0,1].tick_params(axis='x', rotation=45)
axes[0,1].grid(True, alpha=0.3, axis='y')

# 5.3 促销vs非促销效果对比
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: '无促销'})

x = np.arange(len(promo_comparison))
width = 0.25
axes[1,0].bar(x - width, promo_comparison['order_id'], width, label='订单数', color='steelblue')
axes[1,0].bar(x, promo_comparison['quantity'], width, label='销售量', color='coral')
axes[1,0].bar(x + width, promo_comparison['total_amount']/100, width, label='销售额/100', color='lightgreen')
axes[1,0].set_xlabel('促销状态', fontsize=12)
axes[1,0].set_ylabel('数值', fontsize=12)
axes[1,0].set_title('有促销 vs 无促销销售效果对比', fontsize=14, fontweight='bold')
axes[1,0].set_xticks(x)
axes[1,0].set_xticklabels(promo_comparison['has_discount'])
axes[1,0].legend()
axes[1,0].grid(True, alpha=0.3, axis='y')

# 5.4 退货率对比
return_rate = df.groupby('category').agg({
    'order_id': 'count',
    'is_returned': 'sum'
}).reset_index()
return_rate['return_rate'] = return_rate['is_returned'] / return_rate['order_id'] * 100
return_rate = return_rate.sort_values('return_rate', ascending=False)

axes[1,1].bar(range(len(return_rate)), return_rate['return_rate'], 
              color=sns.color_palette("RdYlGn_r", len(return_rate)))
axes[1,1].set_xticks(range(len(return_rate)))
axes[1,1].set_xticklabels(return_rate['category'], rotation=15)
axes[1,1].set_xlabel('产品类别', fontsize=12)
axes[1,1].set_ylabel('退货率 (%)', fontsize=12)
axes[1,1].set_title('各品类退货率对比', fontsize=14, fontweight='bold')
for i, v in enumerate(return_rate['return_rate'].values):
    axes[1,1].text(i, v, f'{v:.2f}%', ha='center', va='bottom', fontsize=10)
axes[1,1].grid(True, alpha=0.3, axis='y')

plt.tight_layout()
plt.savefig('../visualization/05_comparison_charts.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/05_comparison_charts.png")
plt.close()

# ============================================
# 二、扩展可视化图表
# ============================================

print("\n" + "=" * 80)
print("【扩展图表】")
print("=" * 80)

# 6. 热力图 - 区域品类销售热力分布
print("\n6. 生成热力图 - 区域品类销售热力分布...")
fig, axes = plt.subplots(1, 2, figsize=(16, 6))

# 6.1 区域-品类销售热力图
heatmap_data = df.groupby(['region', 'category'])['total_amount'].sum().unstack()
sns.heatmap(heatmap_data, annot=True, fmt='.0f', cmap='YlOrRd', ax=axes[0], cbar_kws={'label': '销售额'})
axes[0].set_title('区域-品类销售热力分布', fontsize=14, fontweight='bold')
axes[0].set_xlabel('产品类别', fontsize=12)
axes[0].set_ylabel('销售区域', fontsize=12)

# 6.2 特征相关性矩阵
numeric_cols = ['quantity', 'unit_price', 'discount_rate', 'total_amount', 
                'cost_price', 'shipping_cost', 'delivery_days']
corr_matrix = df[numeric_cols].corr()
sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='coolwarm', center=0, 
            square=True, ax=axes[1], cbar_kws={'label': '相关系数'})
axes[1].set_title('特征相关性矩阵', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('../visualization/06_heatmaps.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/06_heatmaps.png")
plt.close()

# 7. 饼图 - 销售占比
print("\n7. 生成饼图 - 销售占比...")
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

# 7.1 品类销售占比
category_pct = df.groupby('category')['total_amount'].sum()
axes[0].pie(category_pct.values, labels=category_pct.index, autopct='%1.1f%%',
            startangle=90, colors=sns.color_palette("pastel"))
axes[0].set_title('品类销售额占比', fontsize=14, fontweight='bold')

# 7.2 区域销售占比
region_pct = df.groupby('region')['total_amount'].sum()
axes[1].pie(region_pct.values, labels=region_pct.index, autopct='%1.1f%%',
            startangle=90, colors=sns.color_palette("Set2"))
axes[1].set_title('区域销售额占比', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('../visualization/07_pie_charts.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/07_pie_charts.png")
plt.close()

# 8. 小提琴图 - 价格和销量分布密度
print("\n8. 生成小提琴图 - 分布密度...")
fig, axes = plt.subplots(1, 2, figsize=(14, 6))

# 8.1 各品类价格分布
sns.violinplot(data=df, x='category', y='unit_price', ax=axes[0], palette='muted')
axes[0].set_xlabel('产品类别', fontsize=12)
axes[0].set_ylabel('单价 (美元)', fontsize=12)
axes[0].set_title('各品类产品价格分布密度', fontsize=14, fontweight='bold')
axes[0].tick_params(axis='x', rotation=15)

# 8.2 各区域订单金额分布
sns.violinplot(data=df, x='region', y='total_amount', ax=axes[1], palette='Set1')
axes[1].set_xlabel('销售区域', fontsize=12)
axes[1].set_ylabel('订单金额 (美元)', fontsize=12)
axes[1].set_title('各区域订单金额分布密度', fontsize=14, fontweight='bold')

plt.tight_layout()
plt.savefig('../visualization/08_violin_plots.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/08_violin_plots.png")
plt.close()

# 9. 堆叠面积图 - 时间序列占比
print("\n9. 生成堆叠面积图 - 时间序列占比...")
monthly_cat = df.groupby(['year_month', 'category'])['total_amount'].sum().unstack(fill_value=0)
fig, ax = plt.subplots(figsize=(14, 7))
monthly_cat.plot(kind='area', stacked=True, ax=ax, alpha=0.7)
ax.set_xlabel('月份', fontsize=12)
ax.set_ylabel('销售额 (美元)', fontsize=12)
ax.set_title('各品类月度销售额堆叠趋势', fontsize=14, fontweight='bold')
ax.legend(title='产品类别', bbox_to_anchor=(1.05, 1), loc='upper left')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('../visualization/09_area_chart.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/09_area_chart.png")
plt.close()

# 10. 雷达图 - 多维度业绩对比
print("\n10. 生成雷达图 - 区域多维度对比...")
from math import pi

# 计算各区域的标准化指标
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:]:
    region_metrics[col] = (region_metrics[col] - region_metrics[col].min()) / \
                          (region_metrics[col].max() - region_metrics[col].min()) * 100

categories = ['销售额', '销售量', '订单数', '平均单价', '配送效率']
N = len(categories)

fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='polar')

angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]

for idx, row in region_metrics.iterrows():
    values = row[['total_amount', 'quantity', 'order_id', 'unit_price', 'delivery_days']].tolist()
    values += values[:1]
    ax.plot(angles, values, 'o-', linewidth=2, label=row['region'])
    ax.fill(angles, values, alpha=0.15)

ax.set_xticks(angles[:-1])
ax.set_xticklabels(categories, fontsize=12)
ax.set_ylim(0, 100)
ax.set_title('不同区域多维度业绩对比雷达图', fontsize=14, fontweight='bold', pad=20)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))
ax.grid(True)

plt.tight_layout()
plt.savefig('../visualization/10_radar_chart.png', dpi=300, bbox_inches='tight')
print("✓ 已保存: visualization/10_radar_chart.png")
plt.close()

print("\n" + "=" * 80)
print("数据可视化任务完成!")
print("=" * 80)
print(f"\n共生成 10 类可视化图表:")
print("  ✓ 必选图表 (5类): 折线图、箱线图、散点图、柱状图、对比图")
print("  ✓ 扩展图表 (5类): 热力图、饼图、小提琴图、堆叠面积图、雷达图")
print(f"\n所有图表已保存至: visualization/ 目录")
