import pandas as pd
import numpy as np
from datetime import timedelta

# 1. 설정 및 시드 고정 (재현성 확보)
np.random.seed(2026)

# 50개 마이크로 풀필먼트 센터(MFC) 및 52주(1년) 기간 설정
N_MFC = 50
WEEKS = 52
mfc_ids = [f'MFC_{str(i).zfill(2)}' for i in range(1, N_MFC + 1)]
start_date = pd.to_datetime('2026-01-05') # 첫째 주 월요일
dates = [start_date + timedelta(weeks=i) for i in range(WEEKS)]

data = []

print("데이터 생성을 시작합니다...")

for mfc in mfc_ids:
    # 지점별 기본 체급 및 운영 효율성 차이 반영
    base_orders = np.random.normal(5000, 800) 
    mfc_inefficiency = np.random.uniform(0.8, 1.2) # 높을수록 운영 비효율
    
    for w, date in enumerate(dates):
        # 1. 외부 요인 플래그 (Weather, Promo)
        # 여름 장마철(25~32주) 및 겨울 폭설기(48~52주)에 기상 악화 확률 증가
        prob_weather = 0.15 if (25 <= w <= 32) or (w >= 48) else 0.02
        extreme_weather_flag = np.random.binomial(1, prob_weather)
        
        # 약 10% 확률로 대규모 프로모션 진행
        promo_active_flag = np.random.binomial(1, 0.1)
        
        # 2. 주문량 (프로모션 시 급증)
        weekly_orders = int(base_orders + promo_active_flag * np.random.normal(2000, 500) + np.random.normal(0, 300))
        weekly_orders = max(weekly_orders, 1000)
        
        # 3. 결품률 (기본 1~3%, 프로모션 시 4~8%로 상승)
        oos_base = np.random.uniform(0.01, 0.03)
        if promo_active_flag == 1:
            oos_base += np.random.uniform(0.03, 0.05)
        out_of_stock_rate = round(oos_base * 100, 2)
        
        # 4. 라이더 대기 시간 (비선형 로직의 핵심)
        # 기본 2~4분, 기상 악화 시 기하급수적 증가, 주문 폭주 시 추가 지연
        rider_wait_time = np.random.uniform(1.5, 3.5) * mfc_inefficiency
        if extreme_weather_flag == 1:
            rider_wait_time += np.random.exponential(3.0) # 꼬리가 긴 지연 발생
        if promo_active_flag == 1:
            rider_wait_time += np.random.uniform(1.0, 3.0)
        rider_wait_time = round(rider_wait_time, 1)
        
        # 5. 오포장 건수 (주문량 및 라이더 재촉(대기시간)에 비례)
        packing_errors = int((weekly_orders / 1000) * np.random.uniform(0.5, 2.0) * mfc_inefficiency)
        if rider_wait_time > 5:
            packing_errors = int(packing_errors * 1.5) # 대기시간 5분 초과 시 조급함으로 실수 50% 증가
            
        # 6. CS 문의 건수 (결품 + 지연 + 오포장의 복합 결과)
        cs_base = weekly_orders * 0.005 # 기본 문의 0.5%
        cs_oos = (out_of_stock_rate / 100) * weekly_orders * 0.4 # 결품의 40%는 CS 항의로 연결
        # 대기시간(배달지연) 5분 초과 시 CS 문의가 비선형적으로 튀는 현상
        cs_wait = (rider_wait_time ** 1.8) * 1.5 if rider_wait_time > 5 else rider_wait_time 
        cs_complaint_cnt = int(cs_base + cs_oos + cs_wait + packing_errors * 0.9)
        
        # 7. 신선식품 폐기 금액 (프로모션 시 재고 소진으로 오히려 줄어듦)
        fresh_waste_amt = int(np.random.normal(500000, 100000))
        if promo_active_flag == 1:
            fresh_waste_amt = int(fresh_waste_amt * 0.6)
            
        # 8. 총운영비 (Target Variable) 계산
        base_fixed_cost = 15_000_000
        var_order_cost = weekly_orders * 1500 # 건당 기본 처리비
        
        # 페널티 비용 (라이더 할증, CS 응대 인건비, 환불 보상금)
        # 라이더 대기시간이 5분을 넘어가면 할증 비용이 기하급수적으로 붙음 (지수 함수 적용)
        wait_penalty_cost = (np.exp(rider_wait_time - 5) * 80000) if rider_wait_time > 5 else 0
        cs_handling_cost = cs_complaint_cnt * 12000 # 건당 응대 및 보상
        packing_error_cost = packing_errors * 8000
        
        total_op_cost = int(base_fixed_cost + var_order_cost + wait_penalty_cost + cs_handling_cost + packing_error_cost + fresh_waste_amt)
        # 무작위 노이즈 추가
        total_op_cost += int(np.random.normal(0, 800000))
        
        # 데이터 적재
        data.append([
            mfc, f"{date.year}-W{str(date.isocalendar()[1]).zfill(2)}", total_op_cost, 
            weekly_orders, out_of_stock_rate, rider_wait_time, fresh_waste_amt, 
            cs_complaint_cnt, packing_errors, extreme_weather_flag, promo_active_flag
        ])

# DataFrame 생성
columns = [
    'mfc_id', 'week', 'total_op_cost', 'weekly_orders', 'out_of_stock_rate',
    'rider_wait_time', 'fresh_waste_amt', 'cs_complaint_cnt', 'packing_errors',
    'extreme_weather_flag', 'promo_active_flag'
]
df = pd.DataFrame(data, columns=columns)

# CSV 저장
file_name = 'quickbite_mfc_dataset.csv'
df.to_csv(file_name, index=False, encoding='utf-8-sig')

print(f"=== 생성 완료 ===")
print(f"총 데이터 수: {len(df)}행")
print(f"저장된 파일명: {file_name}")
print("\n[상위 5개 데이터 미리보기]")
print(df.head())