import csv, random, datetime, os
random.seed(20260731)
OUT="/mnt/user-data/outputs/smore-sales-data"; os.makedirs(OUT,exist_ok=True)

regions=[(1,"Midwest"),(2,"Northeast"),(3,"South"),(4,"West")]
products=[
 (4011,"Graham Crackers, Honey","Crackers",0,3.49),
 (4012,"Graham Crackers, Organic Honey","Crackers",1,4.99),
 (4013,"Graham Crackers, Cinnamon","Crackers",0,3.79),
 (4021,"Marshmallows, Classic","Marshmallows",0,2.29),
 (4022,"Marshmallows, Organic Vanilla","Marshmallows",1,4.49),
 (4023,"Marshmallows, Jumbo","Marshmallows",0,3.19),
 (4024,"Marshmallows, Mini","Marshmallows",0,1.99),
 (4031,"Chocolate Bar, Milk","Chocolate",0,1.89),
 (4032,"Chocolate Bar, Dark 70%","Chocolate",0,2.59),
 (4033,"Chocolate Bar, Organic Milk","Chocolate",1,3.29),
 (4034,"Chocolate Bar, Sea Salt","Chocolate",0,2.89),
 (4041,"S'more Kit, Campfire Classic","Kits",0,12.99),
 (4042,"S'more Kit, Deluxe Organic","Kits",1,19.99),
 (4043,"S'more Kit, Party Pack (24)","Kits",0,34.99),
 (4051,"Roasting Sticks, Telescoping","Accessories",0,8.99),
 (4052,"Fire Pit Tray, Tabletop","Accessories",0,24.99),
]
segments=["Grocery","Convenience","Campground","Online","Big Box"]
first=["Northern","Lakeside","Summit","Riverbend","Copper","Birch","Hollow","Granite","Cedar",
       "Willow","Harvest","Prairie","Anchor","Beacon","Trailhead","Foxglove","Kettle","Maple",
       "Ridgeline","Stillwater"]
second=["Market","Provisions","Outfitters","Grocers","Trading Co.","Mercantile","Supply","Foods"]
REGNAME={k:v for k,v in regions}
customers=[];ck=1000
for f in first:
    for s in second:
        if len(customers)>=120: break
        customers.append((ck,f+" "+s,random.choice(segments),REGNAME[random.choice(regions)[0]]));ck+=1

start=datetime.date(2024,1,1);end=datetime.date(2026,6,30)
dates=[];d=start
while d<=end: dates.append(d);d+=datetime.timedelta(days=1)
SEAS={1:.4,2:.4,3:.6,4:.9,5:1.6,6:2.2,7:2.4,8:2.2,9:1.4,10:.8,11:.5,12:.7}
dw=[SEAS[x.month] for x in dates]

QTYS=[2,3,4,6,6,8,9,12,12,12,16,18,24,24,30,36,48,60,72,96,120,144]
DISCS=[round(1-i/100,2) for i in range(0,26)]  # 1.00 down to 0.75

TARGET_DISTINCT=3601
TARGET_ROWS=12000

rows=[];seen=set();sk=1
# Phase 1: grow until we have exactly TARGET_DISTINCT distinct SalesAmount values
while len(seen)<TARGET_DISTINCT:
    dt=random.choices(dates,weights=dw,k=1)[0]
    p=random.choice(products);c=random.choice(customers)
    qty=random.choice(QTYS);unit=round(p[4]*random.choice(DISCS),2)
    amt=f"{round(unit*qty,2):.2f}"
    if amt in seen and len(seen)>=TARGET_DISTINCT: continue
    rows.append([sk,dt.isoformat(),p[0],c[0],qty,f"{unit:.2f}",amt]);seen.add(amt);sk+=1
# Phase 2: fill to TARGET_ROWS reusing only amounts already seen
while len(rows)<TARGET_ROWS:
    dt=random.choices(dates,weights=dw,k=1)[0]
    p=random.choice(products);c=random.choice(customers)
    qty=random.choice(QTYS);unit=round(p[4]*random.choice(DISCS),2)
    amt=f"{round(unit*qty,2):.2f}"
    if amt not in seen: continue
    rows.append([sk,dt.isoformat(),p[0],c[0],qty,f"{unit:.2f}",amt]);sk+=1

random.shuffle(rows)
for i,r in enumerate(rows,1): r[0]=i

def w(name,header,data):
    with open(f"{OUT}/{name}.csv","w",newline="",encoding="utf-8") as f:
        wr=csv.writer(f);wr.writerow(header);wr.writerows(data)

w("DimProduct",["ProductKey","ProductName","Category","IsOrganic","ListUnitPrice"],products)
w("DimCustomer",["CustomerKey","CustomerName","Segment","RegionName"],customers)
w("DimDate",["Date","Year","Quarter","MonthNumber","MonthName","DayOfWeek","IsWeekend"],
  [(x.isoformat(),x.year,f"Q{(x.month-1)//3+1}",x.month,x.strftime("%B"),x.strftime("%A"),
    1 if x.weekday()>=5 else 0) for x in dates])
w("FactSmoreSales",["SalesKey","Date","ProductKey","CustomerKey","Quantity","UnitPrice","SalesAmount"],rows)

qd=len(set(r[4] for r in rows));ad=len(set(r[6] for r in rows));ud=len(set(r[5] for r in rows))
tq=sum(r[4] for r in rows);ts=round(sum(float(r[6]) for r in rows),2)
midcust={c[0] for c in customers if c[3]=="Midwest"}
midrows=[r for r in rows if r[3] in midcust]
print("FACT rows            :",len(rows))
print("distinct Quantity    :",qd)
print("distinct UnitPrice   :",ud)
print("distinct SalesAmount :",ad,"  <-- target 3601")
print("Total Quantity       :",tq)
print("Total Sales          :",ts)
print("Midwest rows         :",len(midrows),"customers:",len(midcust))
print("Midwest Total Sales  :",round(sum(float(r[6]) for r in midrows),2))
print("DimDate rows         :",len(dates))
