#!/usr/bin/env python3
"""
被激活的课程数统计：一个 character + 一个 level = 一个课程
- 激活：bi_vala_seasonal_ticket, status=1, deleted_at IS NULL, character_id IS NOT NULL
- 完课：bi_user_chapter_play_record, play_status=1, created_at 在最近14天, 课程level匹配
"""

import psycopg2
from collections import defaultdict

PG_CONFIG = {
    'host': 'bj-postgres-16pob4sg.sql.tencentcdb.com',
    'port': 28591,
    'user': 'ai_member',
    'password': "LdfjdjL83h3h3^$&**YGG*",
    'dbname': 'vala_bi'
}

WINDOW_START = '2026-05-09'
WINDOW_END = '2026-05-23'

conn = psycopg2.connect(**PG_CONFIG)
cur = conn.cursor()

# ===== 1. Get activated courses: (character_id, level) =====
print("1. 查询被激活的课程...")
cur.execute("""
    SELECT DISTINCT character_id, season_package_level
    FROM bi_vala_seasonal_ticket
    WHERE status = 1
      AND deleted_at IS NULL
      AND season_package_level IN ('A1', 'A2')
      AND character_id IS NOT NULL
""")

# Map: level_code ('A1','A2') -> set of character_ids
activated_courses = defaultdict(set)
for row in cur.fetchall():
    cid, level = row
    activated_courses[level].add(cid)

l1_chars = activated_courses['A1']
l2_chars = activated_courses['A2']
both_chars = l1_chars & l2_chars

print(f"   L1激活课程数 (character+level): {len(l1_chars)}")
print(f"   L2激活课程数 (character+level): {len(l2_chars)}")
print(f"   去重后总激活课程数: {len(l1_chars | l2_chars)}")

# Show overlap
only_l1 = l1_chars - l2_chars
only_l2 = l2_chars - l1_chars
print(f"   仅L1激活的角色: {len(only_l1)}")
print(f"   仅L2激活的角色: {len(only_l2)}")
print(f"   L1+L2都激活的角色: {len(both_chars)}")

# ===== 2. Get course level mapping =====
print("\n2. 查询课程等级映射...")
cur.execute("SELECT id, course_level FROM bi_level_unit_lesson WHERE course_level IN ('L1', 'L2')")
chapter_level = {row[0]: row[1] for row in cur.fetchall()}

# ===== 3. Get study records by character =====
print("3. 查询最近14天完课记录...")

all_chars = l1_chars | l2_chars
mod_buckets = defaultdict(set)
for cid in all_chars:
    mod_buckets[cid % 8].add(cid)

char_level_study = defaultdict(set)  # character_id -> set of course_level studied

for mod_val in range(8):
    uids_in_mod = mod_buckets.get(mod_val, set())
    if not uids_in_mod:
        continue
    uid_list = list(uids_in_mod)
    for j in range(0, len(uid_list), 500):
        batch = uid_list[j:j+500]
        cur.execute(f"""
            SELECT DISTINCT pr.user_id, cl.course_level
            FROM bi_user_chapter_play_record_{mod_val} pr
            JOIN bi_level_unit_lesson cl ON pr.chapter_id = cl.id
            WHERE pr.user_id = ANY(%s)
              AND pr.play_status = 1
              AND pr.created_at >= %s
              AND pr.created_at < %s
              AND cl.course_level IN ('L1', 'L2')
        """, (batch, WINDOW_START, WINDOW_END))
        for row in cur.fetchall():
            char_level_study[row[0]].add(row[1])

print(f"   最近14天有完课的角色数: {len(char_level_study)}")

# ===== 4. Calculate =====
print("\n===== 计算结果 =====\n")

level_map = {'A1': 'L1', 'A2': 'L2'}

# For each activated course (character, level), check if studied
totals = {}
for db_level, label in [('A1', 'L1'), ('A2', 'L2')]:
    chars = activated_courses[db_level]
    studied = 0
    not_studied = 0
    for cid in chars:
        char_levels = char_level_study.get(cid, set())
        if label in char_levels:
            studied += 1
        else:
            not_studied += 1

    total = studied + not_studied
    totals[db_level] = {
        'total': total,
        'studied': studied,
        'not_studied': not_studied,
        'pct': studied / total * 100 if total else 0
    }
    print(f"【{label} 激活课程】 共 {total} 门")
    print(f"  近14天有完课: {studied} ({studied/total*100:.1f}%)")
    print(f"  近14天无完课: {not_studied} ({not_studied/total*100:.1f}%)")
    print()

# Combined
total_courses = len(l1_chars | l2_chars)
# A character can have both L1 and L2, so total courses >= total unique characters
# Total activated course units = L1 courses + L2 courses
total_units = totals['A1']['total'] + totals['A2']['total']
total_studied = totals['A1']['studied'] + totals['A2']['studied']

print(f"【总体】")
print(f"  激活课程总数（去重角色+去重等级）: {total_courses} 门课程")
print(f"  激活课程总数（L1+L2独立计数）: {total_units} 个课程单位")
print(f"  近14天有完课: {total_studied} ({total_studied/total_units*100:.1f}%)")
print(f"  近14天无完课: {total_units - total_studied} ({(total_units - total_studied)/total_units*100:.1f}%)")

# Cross-tab for characters with both L1+L2 activated
print(f"\n【L1+L2双激活角色】 共 {len(both_chars)} 个角色")
both_l1_studied = 0
both_l2_studied = 0
both_both = 0
both_neither = 0
for cid in both_chars:
    levels = char_level_study.get(cid, set())
    has_l1 = 'L1' in levels
    has_l2 = 'L2' in levels
    if has_l1 and has_l2:
        both_both += 1
        both_l1_studied += 1
        both_l2_studied += 1
    elif has_l1:
        both_l1_studied += 1
    elif has_l2:
        both_l2_studied += 1
    else:
        both_neither += 1

n = len(both_chars) if both_chars else 1
print(f"  仅L1有完课: {both_l1_studied - both_both} 个 ({(both_l1_studied - both_both)/n*100:.1f}%)")
print(f"  仅L2有完课: {both_l2_studied - both_both} 个 ({(both_l2_studied - both_both)/n*100:.1f}%)")
print(f"  L1+L2都有: {both_both} 个 ({both_both/n*100:.1f}%)")
print(f"  都无完课: {both_neither} 个 ({both_neither/n*100:.1f}%)")

cur.close()
conn.close()
