#!/usr/bin/env python3
"""分析完课记录表，生成两张柱状图"""
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
import os

plt.rcParams['font.sans-serif'] = ['WenQuanYi Micro Hei', 'SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

# ===== 读取数据 =====
input_path = '/root/.openclaw/workspace/tmp/inbound_file.xlsx'
output_dir = '/root/.openclaw/workspace/output'
os.makedirs(output_dir, exist_ok=True)

df = pd.read_excel(input_path, sheet_name='完课记录')
print(f"总行数: {len(df)}")
print(f"列名: {df.columns.tolist()}")
print(df.head(10))

cols = df.columns.tolist()
user_id_col = cols[0]   # 用户ID
role_id_col = cols[1]   # 角色ID
course_col = cols[2]    # 课程名称
time_col = cols[3]      # 完课耗时(分钟)
first_col = cols[4]     # 是否首通

# ===== 图1：单个课程用户作答次数分布 =====
# 按 (角色ID, 课程名称) 分组，统计每人每课作答次数
attempt_counts = df.groupby([role_id_col, course_col]).size().reset_index(name='attempts')
print(f"\n=== 作答次数统计 ===")
print(f"唯一 (角色, 课程) 组合数: {len(attempt_counts)}")
print(attempt_counts['attempts'].describe())

# 统计作答次数的分布
attempt_dist = attempt_counts['attempts'].value_counts().sort_index()
print(f"\n作答次数分布 (前20):")
for k, v in attempt_dist.head(20).items():
    print(f"  作答{k}次: {v}人")

# 作图 - 作答次数分布
fig, ax = plt.subplots(figsize=(14, 6))

# 为了图表清晰，处理长尾：作答次数<=30的单独画，>30的合并
max_bins = 30
attempt_dist_plot = attempt_dist.copy()
# 只显示 <=max_bins 的
attempt_dist_plot = attempt_dist_plot[attempt_dist_plot.index <= max_bins]
# 把 >max_bins 的合并
overflow = attempt_dist[attempt_dist.index > max_bins]
if len(overflow) > 0:
    attempt_dist_plot[max_bins + 1] = overflow.sum()
    labels = [str(i) for i in range(1, max_bins + 1)] + [f'{max_bins+1}+']
else:
    labels = [str(i) for i in attempt_dist_plot.index]

colors = ['#5B9BD5' if i <= 5 else '#ED7D31' if i <= 15 else '#A5A5A5' for i in attempt_dist_plot.index]
bars = ax.bar(range(len(attempt_dist_plot)), attempt_dist_plot.values, color=colors, edgecolor='white', linewidth=0.5)

# 在柱子上标注数值（只标前几个和最后的）
for i, (bar, val) in enumerate(zip(bars, attempt_dist_plot.values)):
    if val >= attempt_dist_plot.values.max() * 0.02:  # 只标注占比>=2%的
        ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + val*0.01, 
                f'{val:,.0f}', ha='center', va='bottom', fontsize=7)

ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels, rotation=0 if len(labels) <= 20 else 45)
ax.set_xlabel('作答次数', fontsize=12)
ax.set_ylabel('人数（角色ID-课程组合数）', fontsize=12)
ax.set_title('单个课程用户作答次数分布', fontsize=14, fontweight='bold')
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'{x:,.0f}'))
ax.set_ylim(0, attempt_dist_plot.values.max() * 1.12)
ax.grid(axis='y', alpha=0.3)

# 添加统计信息
stats_text = f'总组合数: {len(attempt_counts):,}\n平均: {attempt_counts["attempts"].mean():.1f}次\n中位数: {attempt_counts["attempts"].median():.0f}次'
ax.text(0.98, 0.95, stats_text, transform=ax.transAxes, fontsize=10,
        verticalalignment='top', horizontalalignment='right',
        bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))

plt.tight_layout()
chart1_path = os.path.join(output_dir, 'course_attempt_distribution.png')
plt.savefig(chart1_path, dpi=150, bbox_inches='tight')
plt.close()
print(f"\n图1已保存: {chart1_path}")

# ===== 图2：首通完课耗时分布 =====
first_pass = df[df[first_col] == '是'].copy()
print(f"\n=== 首通记录统计 ===")
print(f"首通记录数: {len(first_pass)}")
print(f"占总记录比例: {len(first_pass)/len(df)*100:.1f}%")

# 按 (角色ID, 课程名称) 取首通的耗时
first_pass_time = first_pass[[role_id_col, course_col, time_col]].copy()
first_pass_time[time_col] = pd.to_numeric(first_pass_time[time_col], errors='coerce')
first_pass_time = first_pass_time.dropna(subset=[time_col])

print(f"有效首通耗时记录: {len(first_pass_time)}")
print(first_pass_time[time_col].describe())

# 耗时分布 - 分段统计
# 定义耗时区间 (分钟)
bins = [0, 5, 10, 15, 20, 25, 30, 40, 50, 60, 90, 120, 180, float('inf')]
bin_labels = ['0-5', '5-10', '10-15', '15-20', '20-25', '25-30', 
              '30-40', '40-50', '50-60', '60-90', '90-120', '120-180', '180+']

# 对每个(角色,课程)的首通取耗时
time_dist = pd.cut(first_pass_time[time_col], bins=bins, labels=bin_labels, right=False)
time_dist_counts = time_dist.value_counts().sort_index()

print(f"\n耗时分布:")
for k, v in time_dist_counts.items():
    print(f"  {k}分钟: {v:,}人")

# 作图 - 首通耗时分布
fig, ax = plt.subplots(figsize=(14, 6))

colors2 = ['#70AD47' if i < 5 else '#FFC000' if i < 9 else '#ED7D31' if i < 11 else '#C00000' for i in range(len(time_dist_counts))]
bars2 = ax.bar(range(len(time_dist_counts)), time_dist_counts.values, color=colors2, edgecolor='white', linewidth=0.5)

for bar, val in zip(bars2, time_dist_counts.values):
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + val*0.01,
            f'{val:,.0f}', ha='center', va='bottom', fontsize=8)

ax.set_xticks(range(len(bin_labels)))
ax.set_xticklabels(bin_labels, rotation=45)
ax.set_xlabel('完课耗时（分钟）', fontsize=12)
ax.set_ylabel('人数（角色ID-课程组合数）', fontsize=12)
ax.set_title('单个课程用户首通完课耗时分布', fontsize=14, fontweight='bold')
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, p: f'{x:,.0f}'))
ax.set_ylim(0, time_dist_counts.values.max() * 1.15)
ax.grid(axis='y', alpha=0.3)

stats_text2 = f'总首通组合数: {len(first_pass_time):,}\n平均耗时: {first_pass_time[time_col].mean():.1f}分钟\n中位数: {first_pass_time[time_col].median():.1f}分钟'
ax.text(0.98, 0.95, stats_text2, transform=ax.transAxes, fontsize=10,
        verticalalignment='top', horizontalalignment='right',
        bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.8))

plt.tight_layout()
chart2_path = os.path.join(output_dir, 'first_pass_time_distribution.png')
plt.savefig(chart2_path, dpi=150, bbox_inches='tight')
plt.close()
print(f"\n图2已保存: {chart2_path}")

# ===== 汇总输出 =====
print("\n" + "="*60)
print("分析完成！")
print(f"图1 - 作答次数分布: {chart1_path}")
print(f"图2 - 首通耗时分布: {chart2_path}")
