"""
Seed realistic test data for local development.

Creates suppliers, leads, a dev user, credit ledger entries, and lead forwards.

Usage:
    uv run python -m padelnomics.scripts.seed_dev_data
"""

import logging
import os
import sqlite3
import sys
from datetime import UTC, datetime, timedelta
from pathlib import Path

from dotenv import load_dotenv

logger = logging.getLogger(__name__)

load_dotenv()

DATABASE_PATH = os.getenv("DATABASE_PATH", "data/app.db")


def slugify(name: str) -> str:
    return name.lower().replace(" ", "-").replace("&", "and").replace(",", "")


SUPPLIERS = [
    {
        "name": "PadelTech GmbH",
        "slug": "padeltech-gmbh",
        "country_code": "DE",
        "city": "Munich",
        "region": "Europe",
        "website": "https://padeltech.example.com",
        "description": "Premium padel court manufacturer with 15+ years experience in Central Europe.",
        "category": "manufacturer",
        "tier": "pro",
        "credit_balance": 80,
        "monthly_credits": 100,
        "contact_name": "Hans Weber",
        "contact_email": "hans@padeltech.example.com",
        "years_in_business": 15,
        "project_count": 120,
        "service_area": "DE,AT,CH",
    },
    {
        "name": "CourtBuild Spain",
        "slug": "courtbuild-spain",
        "country_code": "ES",
        "city": "Madrid",
        "region": "Europe",
        "website": "https://courtbuild.example.com",
        "description": "Turnkey padel facility builder serving Spain and Portugal.",
        "category": "turnkey",
        "tier": "growth",
        "credit_balance": 25,
        "monthly_credits": 30,
        "contact_name": "Maria Garcia",
        "contact_email": "maria@courtbuild.example.com",
        "years_in_business": 8,
        "project_count": 45,
        "service_area": "ES,PT",
    },
    {
        "name": "Nordic Padel Solutions",
        "slug": "nordic-padel-solutions",
        "country_code": "SE",
        "city": "Stockholm",
        "region": "Europe",
        "website": "https://nordicpadel.example.com",
        "description": "Indoor padel specialists for the Nordic climate.",
        "category": "manufacturer",
        "tier": "free",
        "credit_balance": 0,
        "monthly_credits": 0,
        "contact_name": "Erik Lindqvist",
        "contact_email": "erik@nordicpadel.example.com",
        "years_in_business": 5,
        "project_count": 20,
        "service_area": "SE,DK,FI,NO",
    },
    {
        "name": "PadelLux Consulting",
        "slug": "padellux-consulting",
        "country_code": "NL",
        "city": "Amsterdam",
        "region": "Europe",
        "website": "https://padellux.example.com",
        "description": "Independent padel consultants helping investors plan profitable facilities.",
        "category": "consultant",
        "tier": "growth",
        "credit_balance": 18,
        "monthly_credits": 30,
        "contact_name": "Jan de Vries",
        "contact_email": "jan@padellux.example.com",
        "years_in_business": 3,
        "project_count": 12,
        "service_area": "NL,BE,DE",
    },
    {
        "name": "Desert Padel FZE",
        "slug": "desert-padel-fze",
        "country_code": "AE",
        "city": "Dubai",
        "region": "Middle East",
        "website": "https://desertpadel.example.com",
        "description": "Outdoor and covered padel courts designed for extreme heat environments.",
        "category": "turnkey",
        "tier": "pro",
        "credit_balance": 90,
        "monthly_credits": 100,
        "contact_name": "Ahmed Al-Rashid",
        "contact_email": "ahmed@desertpadel.example.com",
        "years_in_business": 6,
        "project_count": 30,
        "service_area": "AE,SA",
    },
]

LEADS = [
    {
        "facility_type": "indoor",
        "court_count": 6,
        "country": "DE",
        "city": "Berlin",
        "timeline": "3-6mo",
        "budget_estimate": 450000,
        "heat_score": "hot",
        "status": "new",
        "contact_name": "Thomas Mueller",
        "contact_email": "thomas@example.com",
        "stakeholder_type": "entrepreneur",
        "financing_status": "loan_approved",
        "location_status": "lease_signed",
        "decision_process": "solo",
    },
    {
        "facility_type": "outdoor",
        "court_count": 4,
        "country": "ES",
        "city": "Barcelona",
        "timeline": "asap",
        "budget_estimate": 280000,
        "heat_score": "hot",
        "status": "new",
        "contact_name": "Carlos Ruiz",
        "contact_email": "carlos@example.com",
        "stakeholder_type": "tennis_club",
        "financing_status": "self_funded",
        "location_status": "permit_granted",
        "decision_process": "partners",
    },
    {
        "facility_type": "both",
        "court_count": 8,
        "country": "SE",
        "city": "Gothenburg",
        "timeline": "6-12mo",
        "budget_estimate": 720000,
        "heat_score": "warm",
        "status": "new",
        "contact_name": "Anna Svensson",
        "contact_email": "anna@example.com",
        "stakeholder_type": "developer",
        "financing_status": "seeking",
        "location_status": "location_found",
        "decision_process": "committee",
    },
    {
        "facility_type": "indoor",
        "court_count": 4,
        "country": "NL",
        "city": "Rotterdam",
        "timeline": "3-6mo",
        "budget_estimate": 350000,
        "heat_score": "warm",
        "status": "new",
        "contact_name": "Pieter van Dijk",
        "contact_email": "pieter@example.com",
        "stakeholder_type": "entrepreneur",
        "financing_status": "self_funded",
        "location_status": "converting_existing",
        "decision_process": "solo",
    },
    {
        "facility_type": "indoor",
        "court_count": 10,
        "country": "DE",
        "city": "Hamburg",
        "timeline": "asap",
        "budget_estimate": 900000,
        "heat_score": "hot",
        "status": "forwarded",
        "contact_name": "Lisa Braun",
        "contact_email": "lisa@example.com",
        "stakeholder_type": "operator",
        "financing_status": "loan_approved",
        "location_status": "permit_pending",
        "decision_process": "partners",
    },
    {
        "facility_type": "outdoor",
        "court_count": 3,
        "country": "AE",
        "city": "Abu Dhabi",
        "timeline": "12+mo",
        "budget_estimate": 200000,
        "heat_score": "cool",
        "status": "new",
        "contact_name": "Fatima Hassan",
        "contact_email": "fatima@example.com",
        "stakeholder_type": "municipality",
        "financing_status": "not_started",
        "location_status": "still_searching",
        "decision_process": "committee",
    },
    {
        "facility_type": "indoor",
        "court_count": 6,
        "country": "FR",
        "city": "Lyon",
        "timeline": "6-12mo",
        "budget_estimate": 500000,
        "heat_score": "warm",
        "status": "new",
        "contact_name": "Jean Dupont",
        "contact_email": "jean@example.com",
        "stakeholder_type": "entrepreneur",
        "financing_status": "seeking",
        "location_status": "location_found",
        "decision_process": "solo",
    },
    {
        "facility_type": "both",
        "court_count": 12,
        "country": "IT",
        "city": "Milan",
        "timeline": "3-6mo",
        "budget_estimate": 1200000,
        "heat_score": "hot",
        "status": "new",
        "contact_name": "Marco Rossi",
        "contact_email": "marco@example.com",
        "stakeholder_type": "developer",
        "financing_status": "loan_approved",
        "location_status": "permit_granted",
        "decision_process": "partners",
    },
    {
        "facility_type": "indoor",
        "court_count": 4,
        "country": "GB",
        "city": "Manchester",
        "timeline": "6-12mo",
        "budget_estimate": 400000,
        "heat_score": "warm",
        "status": "pending_verification",
        "contact_name": "James Wilson",
        "contact_email": "james@example.com",
        "stakeholder_type": "tennis_club",
        "financing_status": "seeking",
        "location_status": "converting_existing",
        "decision_process": "committee",
    },
    {
        "facility_type": "outdoor",
        "court_count": 2,
        "country": "PT",
        "city": "Lisbon",
        "timeline": "12+mo",
        "budget_estimate": 150000,
        "heat_score": "cool",
        "status": "new",
        "contact_name": "Sofia Costa",
        "contact_email": "sofia@example.com",
        "stakeholder_type": "entrepreneur",
        "financing_status": "not_started",
        "location_status": "still_searching",
        "decision_process": "solo",
    },
]


AFFILIATE_PRODUCTS = [
    # Rackets
    {
        "slug": "bullpadel-vertex-04-amazon",
        "name": "Bullpadel Vertex 04",
        "brand": "Bullpadel",
        "category": "racket",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST01?tag=padelnomics-21",
        "price_cents": 17999,
        "rating": 4.7,
        "pros": '["Carbon-Rahmen für maximale Power", "Diamant-Form für aggressive Spieler", "Sehr gute Balance"]',
        "cons": '["Nur für fortgeschrittene Spieler", "Höherer Preis"]',
        "description": "Der Vertex 04 ist der Flaggschiff-Schläger von Bullpadel für Power-Spieler.",
        "status": "active",
        "language": "de",
        "sort_order": 1,
    },
    {
        "slug": "head-delta-pro-amazon",
        "name": "HEAD Delta Pro",
        "brand": "HEAD",
        "category": "racket",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST02?tag=padelnomics-21",
        "price_cents": 14999,
        "rating": 4.5,
        "pros": '["Sehr kontrollorientiert", "Ideal für Defensivspieler", "Leicht"]',
        "cons": '["Weniger Power als Diamant-Formen"]',
        "description": "Runde Form mit perfekter Kontrolle — ideal für Einsteiger und Defensivspieler.",
        "status": "active",
        "language": "de",
        "sort_order": 2,
    },
    {
        "slug": "adidas-metalbone-30-amazon",
        "name": "Adidas Metalbone 3.0",
        "brand": "Adidas",
        "category": "racket",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST03?tag=padelnomics-21",
        "price_cents": 18999,
        "rating": 4.8,
        "pros": '["Brutale Power", "Hochwertige Verarbeitung", "Sehr beliebt auf Pro-Tour"]',
        "cons": '["Teuer", "Gewöhnungsbedürftig"]',
        "description": "Das Flaggschiff von Adidas Padel — getragen von den besten Profis der Welt.",
        "status": "active",
        "language": "de",
        "sort_order": 3,
    },
    {
        "slug": "wilson-bela-pro-v2-amazon",
        "name": "Wilson Bela Pro v2",
        "brand": "Wilson",
        "category": "racket",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST04?tag=padelnomics-21",
        "price_cents": 16999,
        "rating": 4.6,
        "pros": '["Bekannter Signature-Schläger", "Gute Mischung aus Power und Kontrolle"]',
        "cons": '["Fortgeschrittene bevorzugt"]',
        "description": "Der Schläger von Fernando Belasteguín — einer der meistgekauften Schläger weltweit.",
        "status": "active",
        "language": "de",
        "sort_order": 4,
    },
    # Beginner racket — draft (tests that draft products are excluded from public)
    {
        "slug": "dunlop-aero-star-amazon",
        "name": "Dunlop Aero Star",
        "brand": "Dunlop",
        "category": "racket",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST05?tag=padelnomics-21",
        "price_cents": 8999,
        "rating": 4.2,
        "pros": '["Günstig", "Für Einsteiger ideal"]',
        "cons": '["Wenig Power für Fortgeschrittene"]',
        "description": "Solider Einsteigerschläger für unter 90 Euro.",
        "status": "draft",
        "language": "de",
        "sort_order": 5,
    },
    # Shoes
    {
        "slug": "adidas-adipower-ctrl-amazon",
        "name": "Adidas Adipower Ctrl",
        "brand": "Adidas",
        "category": "shoe",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST10?tag=padelnomics-21",
        "price_cents": 9999,
        "rating": 4.4,
        "pros": '["Hervorragender Halt auf Sand", "Leicht und atmungsaktiv"]',
        "cons": '["Größenfehler möglich — eine Größe größer bestellen"]',
        "description": "Professioneller Padelschuh mit optimierter Sohle für Sand- und Kunstrasencourts.",
        "status": "active",
        "language": "de",
        "sort_order": 1,
    },
    {
        "slug": "babolat-jet-premura-amazon",
        "name": "Babolat Jet Premura",
        "brand": "Babolat",
        "category": "shoe",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST11?tag=padelnomics-21",
        "price_cents": 11999,
        "rating": 4.6,
        "pros": '["Sehr leicht", "Gute Dämpfung", "Stylisches Design"]',
        "cons": '["Teurer als Mitbewerber"]',
        "description": "Ultraleichter Padelschuh von Babolat — ideal für schnelle Spieler.",
        "status": "active",
        "language": "de",
        "sort_order": 2,
    },
    # Balls
    {
        "slug": "head-padel-pro-balls-amazon",
        "name": "HEAD Padel Pro Bälle (3er-Dose)",
        "brand": "HEAD",
        "category": "ball",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST20?tag=padelnomics-21",
        "price_cents": 799,
        "rating": 4.5,
        "pros": '["Offizieller Turnierball", "Guter Druckerhalt", "Günstig"]',
        "cons": '["Bei intensivem Spiel nach 4–5 Sessions platter"]',
        "description": "Offizieller Turnierball von HEAD — der am häufigsten gespielte Padelball in Europa.",
        "status": "active",
        "language": "de",
        "sort_order": 1,
    },
    # Grips/Accessories
    {
        "slug": "bullpadel-overgrip-3er-amazon",
        "name": "Bullpadel Overgrip (3er-Pack)",
        "brand": "Bullpadel",
        "category": "grip",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST30?tag=padelnomics-21",
        "price_cents": 499,
        "rating": 4.3,
        "pros": '["Günstig", "Guter Halt auch bei Schweiß", "Einfach zu wechseln"]',
        "cons": '["Hält weniger lang als Originalgriff"]',
        "description": "Günstiges Overgrip-Set — jeder Padelspieler sollte regelmäßig wechseln.",
        "status": "active",
        "language": "de",
        "sort_order": 1,
    },
    {
        "slug": "nox-padel-bag-amazon",
        "name": "NOX ML10 Schläger-Tasche",
        "brand": "NOX",
        "category": "accessory",
        "retailer": "Amazon",
        "affiliate_url": "https://www.amazon.de/dp/B0CXTEST40?tag=padelnomics-21",
        "price_cents": 5999,
        "rating": 4.4,
        "pros": '["Platz für 2 Schläger", "Gepolstertes Schlägerfach", "Robustes Material"]',
        "cons": '["Kein Schuhfach"]',
        "description": "Praktische Padelschläger-Tasche mit Platz für 2 Schläger und Zubehör.",
        "status": "active",
        "language": "de",
        "sort_order": 1,
    },
]

# Article slugs for realistic click referrers
_ARTICLE_SLUGS = [
    "beste-padelschlaeger-2026",
    "padelschlaeger-anfaenger",
    "padelschuhe-test",
    "padelbaelle-vergleich",
    "padel-zubehoer",
]


def main():
    db_path = DATABASE_PATH
    if not Path(db_path).exists():
        logger.error("Database not found at %s. Run migrations first.", db_path)
        sys.exit(1)

    conn = sqlite3.connect(db_path)
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA foreign_keys=ON")
    conn.row_factory = sqlite3.Row

    now = datetime.now(UTC)

    # 1. Create dev user
    logger.info("Creating dev user (dev@localhost)...")
    existing = conn.execute("SELECT id FROM users WHERE email = 'dev@localhost'").fetchone()
    if existing:
        dev_user_id = existing["id"]
        logger.info("  Already exists (id=%s)", dev_user_id)
    else:
        cursor = conn.execute(
            "INSERT INTO users (email, name, created_at) VALUES (?, ?, ?)",
            ("dev@localhost", "Dev User", now.strftime("%Y-%m-%d %H:%M:%S")),
        )
        dev_user_id = cursor.lastrowid
        logger.info("  Created (id=%s)", dev_user_id)

    # Grant admin role to dev user
    conn.execute(
        "INSERT OR IGNORE INTO user_roles (user_id, role) VALUES (?, 'admin')",
        (dev_user_id,),
    )
    logger.info("  Admin role granted")

    # 2. Seed suppliers
    logger.info("Seeding %s suppliers...", len(SUPPLIERS))
    supplier_ids = {}
    for s in SUPPLIERS:
        existing = conn.execute("SELECT id FROM suppliers WHERE slug = ?", (s["slug"],)).fetchone()
        if existing:
            supplier_ids[s["slug"]] = existing["id"]
            logger.info("  %s already exists (id=%s)", s["name"], existing["id"])
            continue

        cursor = conn.execute(
            """INSERT INTO suppliers
               (name, slug, country_code, city, region, website, description, category,
                tier, credit_balance, monthly_credits, contact_name, contact_email,
                years_in_business, project_count, service_area, created_at)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
            (
                s["name"], s["slug"], s["country_code"], s["city"], s["region"],
                s["website"], s["description"], s["category"], s["tier"],
                s["credit_balance"], s["monthly_credits"], s["contact_name"],
                s["contact_email"], s["years_in_business"], s["project_count"],
                s["service_area"], now.strftime("%Y-%m-%d %H:%M:%S"),
            ),
        )
        supplier_ids[s["slug"]] = cursor.lastrowid
        logger.info("  %s -> id=%s", s["name"], cursor.lastrowid)

    # 3. Claim paid suppliers — each gets its own owner user + subscription
    logger.info("Claiming paid suppliers with owner accounts...")
    claimed_suppliers = [
        ("padeltech-gmbh", "supplier_pro", "hans@padeltech.example.com", "Hans Weber"),
        ("courtbuild-spain", "supplier_growth", "maria@courtbuild.example.com", "Maria Garcia"),
        ("desert-padel-fze", "supplier_pro", "ahmed@desertpadel.example.com", "Ahmed Al-Rashid"),
    ]
    period_end = (now + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S")
    for slug, plan, email, name in claimed_suppliers:
        sid = supplier_ids.get(slug)
        if not sid:
            continue

        # Create or find owner user
        existing_owner = conn.execute(
            "SELECT id FROM users WHERE email = ?", (email,)
        ).fetchone()
        if existing_owner:
            owner_id = existing_owner["id"]
        else:
            cursor = conn.execute(
                "INSERT INTO users (email, name, created_at) VALUES (?, ?, ?)",
                (email, name, now.strftime("%Y-%m-%d %H:%M:%S")),
            )
            owner_id = cursor.lastrowid

        # Claim the supplier
        conn.execute(
            "UPDATE suppliers SET claimed_by = ?, claimed_at = ? WHERE id = ? AND claimed_by IS NULL",
            (owner_id, now.strftime("%Y-%m-%d %H:%M:%S"), sid),
        )

        # Create billing customer record
        existing_bc = conn.execute(
            "SELECT id FROM billing_customers WHERE user_id = ?", (owner_id,)
        ).fetchone()
        if not existing_bc:
            conn.execute(
                """INSERT INTO billing_customers (user_id, provider_customer_id, created_at)
                   VALUES (?, ?, ?)""",
                (owner_id, f"ctm_dev_{slug}", now.strftime("%Y-%m-%d %H:%M:%S")),
            )

        # Create active subscription
        existing_sub = conn.execute(
            "SELECT id FROM subscriptions WHERE user_id = ?", (owner_id,)
        ).fetchone()
        if not existing_sub:
            conn.execute(
                """INSERT INTO subscriptions
                   (user_id, plan, status, provider_subscription_id,
                    current_period_end, created_at)
                   VALUES (?, ?, 'active', ?, ?, ?)""",
                (owner_id, plan, f"sub_dev_{slug}",
                 period_end, now.strftime("%Y-%m-%d %H:%M:%S")),
            )
        logger.info("  %s -> owner %s (%s)", slug, email, plan)

    # 4. Seed leads
    logger.info("Seeding %s leads...", len(LEADS))
    lead_ids = []
    for i, lead in enumerate(LEADS):
        from padelnomics.credits import HEAT_CREDIT_COSTS
        credit_cost = HEAT_CREDIT_COSTS.get(lead["heat_score"], 8)
        verified_at = (now - timedelta(hours=i * 2)).isoformat() if lead["status"] not in ("pending_verification",) else None

        cursor = conn.execute(
            """INSERT INTO lead_requests
               (user_id, lead_type, facility_type, court_count, country, location, timeline,
                budget_estimate, heat_score, status, contact_name, contact_email,
                stakeholder_type, financing_status, location_status, decision_process,
                credit_cost, verified_at, created_at)
               VALUES (?, 'quote', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
            (
                dev_user_id, lead["facility_type"], lead["court_count"], lead["country"],
                lead["city"], lead["timeline"], lead["budget_estimate"],
                lead["heat_score"], lead["status"], lead["contact_name"],
                lead["contact_email"], lead["stakeholder_type"],
                lead["financing_status"], lead["location_status"],
                lead["decision_process"], credit_cost, verified_at,
                (now - timedelta(hours=i * 3)).isoformat(),
            ),
        )
        lead_ids.append(cursor.lastrowid)
        logger.info("  Lead #%s: %s (%s, %s)", cursor.lastrowid, lead["contact_name"], lead["heat_score"], lead["country"])

    # 5. Add credit ledger entries for claimed suppliers
    logger.info("Adding credit ledger entries...")
    for slug in ("padeltech-gmbh", "courtbuild-spain", "desert-padel-fze"):
        sid = supplier_ids.get(slug)
        if not sid:
            continue
        is_pro = slug in ("padeltech-gmbh", "desert-padel-fze")
        monthly = 100 if is_pro else 30
        # Monthly allocation
        conn.execute(
            """INSERT INTO credit_ledger (supplier_id, delta, balance_after, event_type, note, created_at)
               VALUES (?, ?, ?, 'monthly_allocation', 'Monthly refill', ?)""",
            (sid, monthly, monthly, (now - timedelta(days=28)).isoformat()),
        )
        # Admin adjustment
        conn.execute(
            """INSERT INTO credit_ledger (supplier_id, delta, balance_after, event_type, note, created_at)
               VALUES (?, ?, ?, 'admin_adjustment', 'Welcome bonus', ?)""",
            (sid, 10, monthly + 10, (now - timedelta(days=25)).isoformat()),
        )
        logger.info("  %s: 2 ledger entries", slug)

    # 6. Add lead forwards for testing
    logger.info("Adding lead forwards...")
    padeltech_id = supplier_ids.get("padeltech-gmbh")
    if padeltech_id and len(lead_ids) >= 2:
        for lead_id in lead_ids[:2]:
            existing = conn.execute(
                "SELECT 1 FROM lead_forwards WHERE lead_id = ? AND supplier_id = ?",
                (lead_id, padeltech_id),
            ).fetchone()
            if not existing:
                conn.execute(
                    """INSERT INTO lead_forwards (lead_id, supplier_id, credit_cost, status, created_at)
                       VALUES (?, ?, ?, 'sent', ?)""",
                    (lead_id, padeltech_id, 35, (now - timedelta(hours=6)).isoformat()),
                )
                conn.execute(
                    "UPDATE lead_requests SET unlock_count = unlock_count + 1 WHERE id = ?",
                    (lead_id,),
                )
                # Ledger entry for spend
                conn.execute(
                    """INSERT INTO credit_ledger (supplier_id, delta, balance_after, event_type, reference_id, note, created_at)
                       VALUES (?, -35, ?, 'lead_unlock', ?, ?, ?)""",
                    (padeltech_id, 80, lead_id, f"Unlocked lead #{lead_id}",
                     (now - timedelta(hours=6)).isoformat()),
                )
                logger.info("  PadelTech unlocked lead #%s", lead_id)

    # 7. Seed affiliate products
    logger.info("Seeding %s affiliate products...", len(AFFILIATE_PRODUCTS))
    product_ids: dict[str, int] = {}
    for p in AFFILIATE_PRODUCTS:
        existing = conn.execute(
            "SELECT id FROM affiliate_products WHERE slug = ? AND language = ?",
            (p["slug"], p["language"]),
        ).fetchone()
        if existing:
            product_ids[p["slug"]] = existing["id"]
            logger.info("  %s already exists (id=%s)", p["name"], existing["id"])
            continue
        cursor = conn.execute(
            """INSERT INTO affiliate_products
               (slug, name, brand, category, retailer, affiliate_url,
                price_cents, currency, rating, pros, cons, description,
                status, language, sort_order)
               VALUES (?, ?, ?, ?, ?, ?, ?, 'EUR', ?, ?, ?, ?, ?, ?, ?)""",
            (
                p["slug"], p["name"], p["brand"], p["category"], p["retailer"],
                p["affiliate_url"], p["price_cents"], p["rating"],
                p["pros"], p["cons"], p["description"],
                p["status"], p["language"], p["sort_order"],
            ),
        )
        product_ids[p["slug"]] = cursor.lastrowid
        logger.info("  %s -> id=%s (%s)", p["name"], cursor.lastrowid, p["status"])

    # 8. Seed affiliate clicks (realistic 30-day spread for dashboard charts)
    logger.info("Seeding affiliate clicks...")
    import random
    rng = random.Random(42)
    # click distribution: more on popular rackets, fewer on accessories
    click_weights = [
        ("bullpadel-vertex-04-amazon", "beste-padelschlaeger-2026", 52),
        ("adidas-metalbone-30-amazon", "beste-padelschlaeger-2026", 41),
        ("head-delta-pro-amazon", "padelschlaeger-anfaenger", 38),
        ("wilson-bela-pro-v2-amazon", "padelschlaeger-anfaenger", 29),
        ("adidas-adipower-ctrl-amazon", "padelschuhe-test", 24),
        ("babolat-jet-premura-amazon", "padelschuhe-test", 18),
        ("head-padel-pro-balls-amazon", "padelbaelle-vergleich", 15),
        ("bullpadel-overgrip-3er-amazon", "padel-zubehoer", 11),
        ("nox-padel-bag-amazon", "padel-zubehoer", 8),
    ]
    existing_click_count = conn.execute("SELECT COUNT(*) FROM affiliate_clicks").fetchone()[0]
    if existing_click_count == 0:
        for slug, article_slug, count in click_weights:
            pid = product_ids.get(slug)
            if not pid:
                continue
            for _ in range(count):
                days_ago = rng.randint(0, 29)
                hours_ago = rng.randint(0, 23)
                clicked_at = (now - timedelta(days=days_ago, hours=hours_ago)).strftime("%Y-%m-%d %H:%M:%S")
                ip_hash = f"dev_{slug}_{_:04d}"  # stable fake hash (not real SHA256)
                conn.execute(
                    """INSERT INTO affiliate_clicks
                       (product_id, article_slug, referrer, ip_hash, clicked_at)
                       VALUES (?, ?, ?, ?, ?)""",
                    (pid, article_slug, f"https://padelnomics.io/de/blog/{article_slug}", ip_hash, clicked_at),
                )
        total_clicks = sum(c for _, _, c in click_weights)
        logger.info("  Inserted %s click events across 9 products", total_clicks)
    else:
        logger.info("  Clicks already seeded (%s rows), skipping", existing_click_count)

    conn.commit()
    conn.close()

    logger.info("Done! Seed data written to %s", db_path)
    logger.info("  Login: /auth/dev-login?email=dev@localhost")
    logger.info("  Admin: set ADMIN_EMAILS=dev@localhost in .env, then dev-login grants admin role")


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO, format="%(levelname)-8s %(message)s")
    main()
