#!/usr/bin/env python3
"""
2026 Battle of the Support Stack: incentive-window comparison.

Tests whether respondents who answered during the KingSumo raffle window
(May 28 - Jun 16, 2026) differ from those who answered outside it, on
sample composition, tool selection, and ratings.

Descriptive by design. With n=80 vs n=51 this is a low-powered comparison,
so absence of a detected difference is weak evidence of no difference.
"""
import csv
from datetime import datetime
from collections import Counter
import numpy as np
from scipy import stats

PATH = '/mnt/user-data/uploads/Battle_of_the_Support_Stack___22026-09-01_11_50_46.csv'
RAFFLE_START, RAFFLE_END = datetime(2026, 5, 28), datetime(2026, 6, 16)

rows = list(csv.reader(open(PATH, encoding='utf-8-sig')))
hdr, data = rows[0], rows[1:]

def dt(r): return datetime.strptime(r[0].strip(), '%b %d, %Y')

inw  = [r for r in data if RAFFLE_START <= dt(r) <= RAFFLE_END]
outw = [r for r in data if not (RAFFLE_START <= dt(r) <= RAFFLE_END)]

print("=" * 74)
print(f"IN raffle window (May 28 - Jun 16): n = {len(inw)}")
print(f"OUT of window (Apr 30 - May 27, Jun 17 - Jul 1): n = {len(outw)}")
print("=" * 74)

# ---------- composition ----------
def compare_cat(idx, label):
    a = Counter(r[idx].strip() for r in inw if r[idx].strip())
    b = Counter(r[idx].strip() for r in outw if r[idx].strip())
    keys = sorted(set(a) | set(b))
    if len(keys) < 2:
        return
    table = np.array([[a.get(k, 0) for k in keys], [b.get(k, 0) for k in keys]])
    keep = table.sum(axis=0) > 0
    table = table[:, keep]
    keys = [k for k, m in zip(keys, keep) if m]
    try:
        chi2, p, _, _ = stats.chi2_contingency(table)
    except ValueError:
        return
    na, nb = table[0].sum(), table[1].sum()
    print(f"\n{label}   (chi-square p = {p:.3f})")
    print(f"  {'level':32} {'in-window':>12} {'outside':>12}")
    for k, ca, cb in zip(keys, table[0], table[1]):
        print(f"  {k[:32]:32} {ca:>5} ({ca/na*100:>4.0f}%) {cb:>5} ({cb/nb*100:>4.0f}%)")

print("\n" + "-" * 74)
print("SAMPLE COMPOSITION")
print("-" * 74)
for idx, lab in [(1, 'Physicians in practice'), (2, 'Years in DPC'),
                 (3, 'Active members'), (61, 'Recruitment source')]:
    compare_cat(idx, lab)

# California specifically
ca_in  = sum(1 for r in inw  if r[4].strip() == 'California')
ca_out = sum(1 for r in outw if r[4].strip() == 'California')
tab = np.array([[ca_in, len(inw) - ca_in], [ca_out, len(outw) - ca_out]])
_, p_ca = stats.fisher_exact(tab)
print(f"\nCalifornia share   (Fisher exact p = {p_ca:.3f})")
print(f"  in-window: {ca_in}/{len(inw)} ({ca_in/len(inw)*100:.0f}%)")
print(f"  outside:   {ca_out}/{len(outw)} ({ca_out/len(outw)*100:.0f}%)")

# ---------- tool mix ----------
CATS = [(5, 'Patient communication'), (11, 'Membership billing'), (17, 'Scheduling'),
        (23, 'Telemedicine'), (29, 'AI & automation'), (35, 'Practice operations'),
        (41, 'HR & payroll'), (47, 'Labs & imaging'), (53, 'Patient education')]

print("\n" + "-" * 74)
print("TOOL SELECTION MIX  (chi-square across all options per category)")
print("-" * 74)
print(f"{'category':24} {'p-value':>9}  {'in-window n':>12} {'outside n':>10}")
for idx, name in CATS:
    a = Counter(r[idx].strip() for r in inw if r[idx].strip())
    b = Counter(r[idx].strip() for r in outw if r[idx].strip())
    keys = sorted(set(a) | set(b))
    table = np.array([[a.get(k, 0) for k in keys], [b.get(k, 0) for k in keys]])
    table = table[:, table.sum(axis=0) > 0]
    try:
        _, p, _, _ = stats.chi2_contingency(table)
        flag = '  <-- differs' if p < 0.05 else ''
        print(f"{name:24} {p:>9.3f}  {table[0].sum():>12} {table[1].sum():>10}{flag}")
    except ValueError:
        print(f"{name:24} {'n/a':>9}  {table[0].sum():>12} {table[1].sum():>10}")

# ---------- ratings ----------
PAIRS = [(5, 7, 8, 'Patient communication'), (11, 13, 14, 'Membership billing'),
         (17, 19, 20, 'Scheduling'), (23, 25, 26, 'Telemedicine'),
         (29, 31, 32, 'AI & automation'), (35, 37, 38, 'Practice operations'),
         (41, 43, 44, 'HR & payroll'), (47, 49, 50, 'Labs & imaging'),
         (53, 55, 56, 'Patient education')]

def nums(group, col):
    out = []
    for r in group:
        v = r[col].strip()
        if v.isdigit():
            out.append(int(v))
    return out

print("\n" + "-" * 74)
print("RATINGS  (Mann-Whitney U, two-sided)")
print("-" * 74)
print(f"{'category / metric':34} {'in':>6} {'out':>6} {'diff':>7} {'p':>8}")
results = []
for sel, r1, r2, name in PAIRS:
    for col, metric in [(r1, 'ease/reliability'), (r2, 'value/pricing')]:
        A, B = nums(inw, col), nums(outw, col)
        if len(A) < 10 or len(B) < 10:
            print(f"{name+' / '+metric:34} {'--':>6} {'--':>6} {'--':>7} {'n<10':>8}")
            continue
        u, p = stats.mannwhitneyu(A, B, alternative='two-sided')
        ma, mb = np.mean(A), np.mean(B)
        results.append(p)
        flag = '  <--' if p < 0.05 else ''
        print(f"{name+' / '+metric:34} {ma:>6.2f} {mb:>6.2f} {ma-mb:>+7.2f} {p:>8.3f}{flag}")

print("\n" + "=" * 74)
sig = sum(1 for p in results if p < 0.05)
print(f"Rating comparisons run: {len(results)}   |   p < 0.05: {sig}")
print(f"Expected false positives at alpha=0.05 with {len(results)} tests: "
      f"{len(results) * 0.05:.1f}")
print("=" * 74)
