#!/usr/bin/env python3
"""Excel v4: L1只看L1课程, L2只看L2课程"""
import json, openpyxl
from datetime import date
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.chart import LineChart, BarChart, Reference
from openpyxl.utils import get_column_letter

with open('/root/.openclaw/workspace/output/course_data_v4.json') as f:
    raw = json.load(f)
results = raw['results']

for r in results:
    r['ws'] = date.fromisoformat(r['ws'])
    r['we'] = date.fromisoformat(r['we'])

wb = openpyxl.Workbook()
wb.remove(wb.active)
hfont = Font(name='微软雅黑', bold=True, size=9, color='FFFFFF')
hfill = PatternFill(start_color='002F5496', end_color='002F5496', fill_type='solid')
dfont = Font(name='微软雅黑', size=9)
tfont = Font(name='微软雅黑', bold=True, size=14, color='002F5496')
sfont = Font(name='微软雅黑', bold=True, size=11, color='002F5496')
bd = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
ctr = Alignment(horizontal='center', vertical='center')

def ac(ws, r, c, v, font=dfont, fill=None, align=ctr):
    cl = ws.cell(row=r, column=c, value=v)
    cl.font, cl.border, cl.alignment = font, bd, align
    if fill: cl.fill = fill

def ah(ws, r, c, v):
    cl = ws.cell(row=r, column=c, value=v)
    cl.font, cl.fill, cl.border, cl.alignment = hfont, hfill, bd, ctr

# Sheet 1
ws1 = wb.create_sheet("概览")
ws1.merge_cells('A1:H1')
ac(ws1,1,1,"付费用户课消分析 v4（只看对应级别课程，剔除U0）",font=tfont,align=Alignment(horizontal='left'))
notes = [
    "口径：L1付费群 = 买过L1商品的付费用户, 只看L1课程课消 | L2付费群 = 买过L2商品的付费用户, 只看L2课程课消",
    "L1+L2用户：在L1视角只统计L1课程课消, L2视角只统计L2课程课消",
    "课消：用户首次完成某一课时（剔除U0序章）",
    "付费用户：status=1 + 未删除 + 有未退款订单",
]
for i,n in enumerate(notes):
    ws1.merge_cells(f'A{3+i}:H{3+i}')
    ac(ws1,3+i,1,n,font=Font(name='微软雅黑',size=9,color='666666'),align=Alignment(horizontal='left'))

row=9
ws1.merge_cells(f'A{row}:H{row}')
ac(ws1,row,1,"汇总（截至最后一周）",font=sfont,align=Alignment(horizontal='left'))
row+=1
for j,h in enumerate(['分类','付费用户','有课消','无课消','无课消率','人均课消','有消人均'],1):
    ah(ws1,row,j,h)
row+=1

last=results[-1]
skus = [
    ('L1付费群(只看L1课程)', last['L1_paid'],last['L1_cons_users'],last['L1_no_cons'],last['L1_avg_all'],last['L1_avg_cons'], '00A8CFF1'),
    ('L2付费群(只看L2课程)', last['L2_paid'],last['L2_cons_users'],last['L2_no_cons'],last['L2_avg_all'],last['L2_avg_cons'], '00F4A9A0'),
    ('合计(去重)', last['total_paid'],last['total_cons_users'],last['total_no_cons'],last['total_avg_all'],last['total_avg_cons'], '00C8E6C9'),
]
for name,p,cu,nc,aa,ac_,clr in skus:
    no_rate=f"{nc/p*100:.0f}%" if p else "0%"
    fl=PatternFill(start_color=clr,end_color=clr,fill_type='solid')
    for j,v in enumerate([name,p,cu,nc,no_rate,aa,ac_],1):
        ac(ws1,row,j,v,font=Font(name='微软雅黑',bold=(j==1),size=10),fill=fl)
    row+=1

# Sheet 2
ws2=wb.create_sheet("每周明细")
headers=['周','周一起','周日']
for pfx in ['合计','L1付费群','L2付费群']:
    for m in ['付费','有消','无消','课消','人均','有消人均']:
        headers.append(f'{pfx}{m}')
for j,h in enumerate(headers,1): ah(ws2,1,j,h)
for ri,r in enumerate(results):
    rw=ri+2
    ac(ws2,rw,1,r['ws'].strftime('%m/%d'))
    ac(ws2,rw,2,r['ws'].strftime('%Y-%m-%d'))
    ac(ws2,rw,3,r['we'].strftime('%Y-%m-%d'))
    col=4
    for prefix in ['total','L1','L2']:
        for k in ['paid','cons_users','no_cons','cons','avg_all','avg_cons']:
            ac(ws2,rw,col,r[f'{prefix}_{k}'])
            col+=1
for ci in range(1,len(headers)+1):
    ws2.column_dimensions[get_column_letter(ci)].width=11 if ci<=3 else 10
ws2.freeze_panes='D2'

# Sheet 3+4: charts
for lvl, pf, clr in [('L1','L1','4A90D9'),('L2','L2','E85D47')]:
    ws=wb.create_sheet(f"{pf}图表")
    lh=['周','付费用户','有课消用户','无课消用户','课消总数','人均课消','有消人均']
    first=next(i for i,r in enumerate(results) if r[f'{pf}_paid']>0)
    ld=results[first:]
    for j,h in enumerate(lh,1): ah(ws,1,j,h)
    for ri,r in enumerate(ld):
        rw=ri+2
        ac(ws,rw,1,r['ws'].strftime('%m/%d'))
        for j,k in enumerate([f'{pf}_paid',f'{pf}_cons_users',f'{pf}_no_cons',f'{pf}_cons',f'{pf}_avg_all',f'{pf}_avg_cons'],2):
            ac(ws,rw,j,r[k])
    n=len(ld)
    cr=Reference(ws,min_col=1,min_row=2,max_row=n+1)
    
    ch1=BarChart(); ch1.type="col"; ch1.grouping="stacked"
    ch1.title=f"{pf}付费用户周课消分布（只看{pf}课程）"; ch1.style=10; ch1.width=24; ch1.height=13
    ch1.add_data(Reference(ws,min_col=3,min_row=1,max_row=n+1),titles_from_data=True)
    ch1.add_data(Reference(ws,min_col=4,min_row=1,max_row=n+1),titles_from_data=True)
    ch1.set_categories(cr)
    ch1.series[0].graphicalProperties.solidFill='A8CFF1' if pf=='L1' else 'F4A9A0'
    ch1.series[1].graphicalProperties.solidFill='D9D9D9'
    ch1.y_axis.title='用户数'; ch1.legend.position='b'
    ws.add_chart(ch1,"A9")
    
    ch2=LineChart(); ch2.title=f"{pf}付费用户周人均课消趋势（只看{pf}课程）"; ch2.style=10; ch2.width=24; ch2.height=13
    ch2.add_data(Reference(ws,min_col=6,min_row=1,max_row=n+1),titles_from_data=True)
    ch2.add_data(Reference(ws,min_col=7,min_row=1,max_row=n+1),titles_from_data=True)
    ch2.set_categories(cr)
    ch2.series[0].graphicalProperties.line.solidFill='999999'; ch2.series[0].graphicalProperties.line.width=20000
    ch2.series[1].graphicalProperties.line.solidFill=clr; ch2.series[1].graphicalProperties.line.width=28000
    ch2.y_axis.scaling.min=0; ch2.y_axis.title='课消数（节/周）'; ch2.legend.position='b'
    ws.add_chart(ch2,"A27")
    for ci in range(1,8): ws.column_dimensions[get_column_letter(ci)].width=12

path='/root/.openclaw/workspace/output/course_consumption_by_level_v4.xlsx'
wb.save(path)
print(f'✅ {path}')
