"""Generate synthetic marketing data with known ground truth for model validation.

Ground truth:
- Google Search: highest ROAS (~3.2x), not yet saturated
- Meta Prospecting: moderate ROAS (~1.8x), heavily saturated above $6K/week
- TikTok: decent ROAS (~2.1x), underinvested (room to grow)

Total weekly revenue baseline: ~$80K with seasonality and noise.
3 channels to fit within the free tier limit.
"""

import argparse
from pathlib import Path

import numpy as np
import pandas as pd


def generate_synthetic_data(
    n_weeks: int = 104,
    seed: int = 42,
    output_path: str | None = None,
) -> pd.DataFrame:
    rng = np.random.default_rng(seed)

    dates = pd.date_range(end=pd.Timestamp.today().normalize(), periods=n_weeks, freq="W-MON")

    # Channel spend patterns (weekly, with some variation)
    channels = {
        "google_search": {
            "base_spend": 5000,
            "spend_std": 800,
            "true_roas": 3.2,
            "saturation_point": 12000,  # high ceiling
        },
        "meta_prospecting": {
            "base_spend": 8000,
            "spend_std": 1200,
            "true_roas": 1.8,
            "saturation_point": 6000,  # low ceiling — already saturated
        },
        "tiktok": {
            "base_spend": 2000,
            "spend_std": 500,
            "true_roas": 2.1,
            "saturation_point": 8000,  # high ceiling — room to grow
        },
    }

    rows = []
    for i, date in enumerate(dates):
        week_data = {"date": date}
        total_revenue = 50000  # organic baseline

        # Seasonality: Q4 boost, Q1 dip
        week_of_year = date.isocalendar()[1]
        seasonality = 1.0 + 0.15 * np.sin(2 * np.pi * (week_of_year - 13) / 52)

        for channel_name, params in channels.items():
            # Generate spend with trend and noise
            trend = 1.0 + 0.001 * i  # slight upward trend
            spend = max(
                0,
                params["base_spend"] * trend + rng.normal(0, params["spend_std"]),
            )

            # Saturating response: revenue = roas * spend * saturation_factor
            saturation_factor = 1 - np.exp(-spend / params["saturation_point"])
            channel_revenue = params["true_roas"] * spend * saturation_factor * seasonality

            # Generate impressions and clicks from spend
            cpm = rng.uniform(8, 15)
            impressions = int(spend / cpm * 1000)
            ctr = rng.uniform(0.01, 0.04)
            clicks = int(impressions * ctr)
            cpc = spend / max(clicks, 1)
            conv_rate = rng.uniform(0.02, 0.06)
            conversions = int(clicks * conv_rate)

            week_data[f"{channel_name}_spend"] = round(spend, 2)
            week_data[f"{channel_name}_impressions"] = impressions
            week_data[f"{channel_name}_clicks"] = clicks
            week_data[f"{channel_name}_conversions"] = conversions

            total_revenue += channel_revenue

        # Add noise to total revenue (seasonality already applied per-channel above)
        noise = rng.normal(0, total_revenue * 0.05)
        week_data["revenue"] = round(total_revenue + noise, 2)

        rows.append(week_data)

    df = pd.DataFrame(rows)

    if output_path is None:
        output_path = str(Path(__file__).parent.parent / "data" / "synthetic_marketing_data.csv")

    Path(output_path).parent.mkdir(parents=True, exist_ok=True)
    df.to_csv(output_path, index=False)
    print(f"Generated {len(df)} weeks of synthetic data → {output_path}")
    print(f"Columns: {list(df.columns)}")
    print(f"Date range: {df['date'].min()} to {df['date'].max()}")
    print(f"Avg weekly revenue: ${df['revenue'].mean():,.0f}")

    return df


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Generate synthetic marketing data")
    parser.add_argument("--weeks", type=int, default=104)
    parser.add_argument("--seed", type=int, default=42)
    parser.add_argument("--output", type=str, default=None)
    args = parser.parse_args()

    generate_synthetic_data(n_weeks=args.weeks, seed=args.seed, output_path=args.output)
