"""QuitSure Discovery V4 — 50-persona content-flow simulation.

Models the REAL audience: dropped-off QuitSure users (completed onboarding, never
started Day 1, already saw the paywall once) who click a REMARKETING EMAIL deep-link.
Distributions match the live cohort (ref: reference_discovery_personalization_data):
~88% India, 80/20 male/female, age skew 25-34, ~10 cigs/day, procrastinator-heavy
"tomorrow" counts. Reproduces the exact shipped copy + personalization from
web/src/app/page.tsx and walks each persona screen-by-screen.

Output: discovery_simulation.html — chat transcripts + auto-flagged content risks +
a "what production personalizes" note per user. For human content review (per Ram).
"""
import html
import random

random.seed(42)

# ── Source data (mirrors page.tsx) ──
EXCUSES = [
    "I'm too stressed right now", "After this project / event / deadline",
    "I'll start Monday", "I need to plan first", "After the holidays",
    "Life will be boring without cigarettes", "Tomorrow", "Just one more pack",
    "I'll quit when I'm ready",
]
TOMORROWS = ["A few times", "10-20 times", "50+ times", "Lost count"]
FEELINGS = ["Tightness in my chest", "Anxiety or panic", "Sadness or loss",
            "Anger or resistance", "Nothing much", "Relief that it's over"]
LOW_FEELINGS = {"Nothing much", "Relief that it's over"}
WHERE = ["My lungs", "My throat", "My head", "My chest"]
OBJECTIONS = ["Not sure it'll work", "Can't afford it right now", "Need to think more", "Bad timing"]
PRICE = {"pay": "$49", "full": "$99", "reward": "$50"}
IN_NAMES = ["Rohan", "Priya", "Arjun", "Anjali", "Vikram", "Sneha", "Karan", "Neha", "Amit", "Pooja", "Rahul", "Divya"]
US_NAMES = ["Mike", "Sarah", "Chris", "Emily", "Jason", "Laura", "Dan", "Megan"]


def top_excuse(ex):
    return ex[0] if ex else "later"  # generic fallback (matches the fixed page.tsx)


def count_react(t):
    return {
        "Lost count": "Lost count. That's not a number, that's a reflex.",
        "50+ times": "50+ times. That means quitting has crossed your mind at least once a week, for years.",
        "10-20 times": "10-20 times. More than you expected?",
    }.get(t, "A few times, but strong enough to make you download this app.")


def response_line(ex):
    n = len(ex)
    ex0 = top_excuse(ex)
    if n == 0:
        return "Even if none felt exact, your brain has its own version, trust me."
    incl = f", including “{ex0}”" if n > 1 else f": “{ex0}”"
    return f"{n} of them{incl}. And here's the thing: you KNOW they aren't real reasons."


def loop_count(t):
    return {"A few times": "a handful of times", "10-20 times": "ten, twenty times",
            "50+ times": "fifty-plus times", "Lost count": "more times than you can count"}.get(t, "countless times")


def case_file(p):
    out = []
    t = p["tomorrow"]
    out.append(("🔁", 'You\'ve said "tomorrow" so many times you lost count.' if t == "Lost count"
                else f'You\'ve said "tomorrow" {t.lower()}.'))
    ex = p["excuses"]
    if ex:
        more = f" and {len(ex) - 1} more" if len(ex) > 1 else ""
        out.append(("🎭", f"Escape hatches you reach for: “{ex[0]}”{more}."))
    f = p["feeling"].lower()
    if p["feeling"] in LOW_FEELINGS:
        out.append(("🤔", f"Quitting didn't even scare you (you felt {f}) — so the only thing keeping you here is a belief."))
    else:
        out.append(("😰", f'Just thinking about quitting triggered {f} — and saying "tomorrow" made it vanish instantly.'))
    out.append(("🚬", "When you actually smoked one, you couldn't find the pleasure." if p["smokeNow"]
                else "When you pictured your last one, you couldn't locate the pleasure."))
    return out


def build_transcript(p):
    ex = p["excuses"]
    ex0 = top_excuse(ex)
    f = p["feeling"]
    low = f in LOW_FEELINGS
    T = []
    c = lambda *m: [T.append(("coach", x)) for x in m]
    u = lambda x: T.append(("user", x))
    note = lambda x: T.append(("note", x))

    note(f"📧 Clicked remarketing email → opened the session. Dropped-off user: finished onboarding, "
         f"never started Day 1, already saw the {PRICE['full']} paywall once. (Production: name “{p['name']}”, "
         f"{p['gender']} voice, ₹ pricing for {p['country']}, and ~{p['cigs']}/day are all KNOWN from the link — "
         f"so the asked questions below would be pre-filled / skipped.)")

    c("Hey 👋 I'm your QuitSure Quit Coach.",
      "You downloaded QuitSure to quit smoking. Then life got in the way, and you never really started.",
      "That's not failure. It's the exact pattern I'm going to show you, in about 8 minutes.",
      f"And just for showing up, you'll earn {PRICE['reward']} off QuitSure. No lectures. No guilt. No health scares.")
    u(f"[tap] Show Me & Earn {PRICE['reward']} (8 min)")

    c('How many times have you told yourself "I\'ll quit Monday" or "I\'ll quit tomorrow"?')
    u(p["tomorrow"])
    c(count_react(p["tomorrow"]), "Now, what do you actually tell yourself to put it off?")
    u("[tap] Let Me Think…")
    c("What do you tell yourself when you delay quitting? Swipe right on the ones that sound like you, left if they don't.")
    u("swiped RIGHT on: " + (", ".join(f"“{e}”" for e in ex) if ex else "(none — swiped left on all 9)"))
    c(response_line(ex), "So why does it work on you, every single time? Watch.")
    u("[tap] Why Does It Keep Working?")
    c(f"Here's what happens every time “{ex0}” shows up:",
      "[loop animation] You didn't choose this. You trained it, until it became a reflex. You're not lazy, and you're not weak. You're trapped in a loop you built.")
    u("[tap] I'm Trapped In It")
    c('Say this out loud, or in your head if you can\'t: "I will never smoke another cigarette. Ever. Starting now."',
      "Say it. Mean it. Feel what happens in your body.")
    u("[tap] I Said It")
    c('[10-second sit, screen nearly empty] "I will never smoke again."')
    c("What did you feel just now? Be honest.")
    u(f)

    # Debrief (collapsed to one screen)
    if low:
        c(f"You felt {f.lower()}. That's rarer, and it tells us something.",
          "If quitting doesn't even scare you, then only one thing is keeping you here: a quiet belief that cigarettes give you something.",
          "So let's test that belief directly. It might be the real lie.")
        u("[tap] Test It")
    else:
        c(f"You survived. You only thought about quitting, your brain hit you with {f.lower()}… and then it passed. Nothing actually happened.",
          "But notice what your brain just did. The instant you'd say “tomorrow,” that feeling vanishes, and that relief feels good. So it learned: saying “tomorrow” = the bad feeling disappears.",
          f"You've run that loop {loop_count(p['tomorrow'])}. It's not a decision anymore, it's a reflex.",
          "And it gets harder the longer you wait, not easier. So you're not weak, you're hooked on the relief of postponing. That's the real thing to break.")
        u("[tap] What Else Is It Wrong About?")

    c(f"So you keep guarding cigarettes with “{ex0}” and the rest. But guard them from what?",
      'Not "smoking is bad for you." You know that.',
      "What if the thing you think you'd miss gives you nothing at all?")
    u("[tap] That Can't Be Right")
    c("Let's do something different. This works best with a real cigarette.", "Can you smoke one right now?")

    if p["smokeNow"]:
        u("[tap] Yes, I Can Smoke Now")
        c("Perfect. Go grab a cigarette and come back, take your time.",
          "We're going to smoke this whole one together. No rush. I'll wait.")
        u("[tap] I've Got One. Ready")
        c("Light it up. Take your first drag, and hold it.",
          "What's actually in this smoke? 7,000 chemicals. Arsenic. Ammonia. Formaldehyde. Feel them coat your throat and fill your lungs.",
          "Now exhale. Was that pleasure? Or was it just… relief?",
          "Here's the thing: you weren't feeling good before this cigarette. You felt a pull. An itch. A restlessness. That drag just brought you back to how a non-smoker feels all day, for free.")
        u("[~14s pause, take another drag] [tap] Continue")
        wq = random.choice(WHERE)
        wr = {"My lungs": "They're burning. That's not pleasure.", "My throat": "It's raw. That's not pleasure.",
              "My head": "That's the nicotine hit, gone in 20 seconds.", "My chest": "That's your heart racing. That's stress, not pleasure."}[wq]
        c("Take another drag, slowly.", "Where exactly in your body is the pleasure right now? Point to it.")
        u(wq)
        c(f"{wr} So where is the “enjoyment” you'd miss?")
        u("[tap] Keep Going")
        c("Now stop paying attention. Go back to normal, let your mind wander, and just finish the cigarette.",
          "While you do, sit with these, one at a time:",
          "[~40s] How many years have you smoked? · Did you plan to smoke this long? · Why did you start? · Is that reason still true?")
        u("[finished the cigarette] [tap] I Finished It")
        c("Welcome back. That last stretch, did you notice the taste? The pleasure? Or were you on autopilot?",
          "That's how you smoke every cigarette. 4,000+ a year. Conscious for maybe the first drag. The rest, your body just… does.",
          "It's not a pleasure. It's an obligation, 10-20 times a day.",
          "[breakdown box] This cigarette: Conscious drags ~2 · Autopilot ~8-12 · Pleasure: first drag only · Time: ~5 min · Added to your life: Nothing",
          f"And “{ex0}”? It's been guarding that, a cigarette you can't even feel.")
        u("[tap] I Can't Unsee This")
    else:
        u("[tap] Not Right Now")
        mem = [
            ("When you took your last drag, did you actually taste it?", ["Yes, I remember the taste", "Not really", "I don't remember"]),
            ("Were you paying attention to the rest of the cigarette?", ["Yes, every drag", "Maybe the first few", "Honestly, no"]),
            ("Where in your body did you feel pleasure?", ["My lungs", "My head", "My chest", "I… can't pinpoint it"]),
            ("What did that cigarette actually add to your day?", ["Enjoyment", "A break from stress", "Just fed a craving", "Nothing specific"]),
        ]
        c("No problem, your memory is honest enough.", "Think of your last cigarette. Picture it clearly.")
        for q, opts in mem:
            c(q); u(random.choice(opts))
        c("Most people can't locate the pleasure. Can't remember the taste. Weren't paying attention past the first drag.",
          f"And “{ex0}”? It's been guarding a habit you don't even experience.",
          "Here's a challenge: your next cigarette today, stay present the whole time. Try to find the pleasure. You'll be shocked.")
        u("[tap] I Can't Unsee This")

    c("Let me show you what you just told me about yourself.")
    for icon, txt in case_file(p):
        note(f"{icon} {txt}")
    c("Put it together: you're not addicted to cigarettes. You're addicted to the relief of postponing them. "
      'Every "tomorrow" is the hit. That\'s the trap. And it\'s the exact thing QuitSure is built to break.')
    u("[tap] So How Do I Break It?")

    c("You've seen the trap. You've seen the cigarette gives you nothing.",
      "Now meet the two people you could become. Both left you a message.",
      f"🔊 [{p['gender']} voice, auto-matched] Future You who started today (warm) + Future You who kept waiting (tired)")
    u("[tap] That's Not the Story I Want")
    c(f"You did it, you've earned your {PRICE['reward']} reward. Here's how to use it:",
      "QuitSure: 6 days to freedom · learn while smoking normally · Day 6 you quit with relief",
      f"{PRICE['full']} → {PRICE['pay']} (your {PRICE['reward']} reward applied) · 21-day money-back guarantee",
      "You just spent 8 minutes seeing through your brain's tricks. Don't give it time to rebuild them.")

    if p["converts"]:
        u(f"[tap] Start QuitSure — {PRICE['pay']}  →  [V3 paywall]")
        note("→ CONVERTED (post-purchase: success → plan → done)")
    else:
        u("[tap] Not right now")
        c("That's okay. The loop doesn't disappear because you learned about it, and neither does your discount.",
          f"We'll keep your {PRICE['pay']} price for 7 days.", "One quick question before you go, what's stopping you?")
        u(p["objection"])
        note("→ tailored reply + testimonials + 'Actually, I'm Ready' recovery")
    return T


def flags(p):
    out = []
    if p["country"] != "US" and PRICE["pay"].startswith("$"):
        out.append(f"This user is {p['country']} but v1 shows {PRICE['pay']} (USD). Production MUST localize to ₹4,999→₹1,999 — the cohort is ~88% India, so this is the norm, not the exception.")
    if p["feeling"] in LOW_FEELINGS:
        out.append("Low-feeling path: Debrief pivots straight to the belief-test, skipping the loop explanation. Verify it lands for someone who felt nothing.")
    if len(p["excuses"]) == 1:
        out.append("Single excuse → Response uses ': “X”' (singular). Check grammar.")
    if not p["excuses"]:
        out.append("Zero excuses → flow now says generic “later” (fixed) instead of a rejected card. Verify it still reads naturally.")
    if not p["converts"] and p["objection"] == "Can't afford it right now" and p["country"] != "US":
        out.append("'Can't afford it' from an India user — the ₹1,999 price (≈ 2 weeks of cigarettes) is the key rebuttal; make sure it shows in ₹.")
    return out


# ── Generate 50 personas with REALISTIC cohort distributions ──
def wpick(opts, weights):
    return random.choices(opts, weights=weights, k=1)[0]

def rand_excuses():
    # procrastinators pick several; few pick 0 or all
    k = wpick([0, 1, 2, 3, 4, 5, 6, 7, 9], [3, 8, 16, 20, 18, 14, 9, 7, 5])
    chosen = set(random.sample(EXCUSES, k))
    return [e for e in EXCUSES if e in chosen]  # preserve card order

personas = []
edge = [
    {"name": "Edge", "tomorrow": "A few times", "excuses": [], "feeling": "Anxiety or panic", "smokeNow": True, "gender": "male", "converts": False, "objection": "Need to think more", "country": "India", "label": "Edge: zero excuses"},
    {"name": "Edge", "tomorrow": "Lost count", "excuses": EXCUSES[:], "feeling": "Tightness in my chest", "smokeNow": True, "gender": "female", "converts": True, "objection": "", "country": "India", "label": "Edge: all 9 excuses"},
    {"name": "Edge", "tomorrow": "50+ times", "excuses": ["Tomorrow"], "feeling": "Nothing much", "smokeNow": True, "gender": "male", "converts": True, "objection": "", "country": "US", "label": "Edge: low feeling + smoke"},
    {"name": "Edge", "tomorrow": "10-20 times", "excuses": ["I'll start Monday", "Tomorrow"], "feeling": "Relief that it's over", "smokeNow": False, "gender": "female", "converts": False, "objection": "Not sure it'll work", "country": "India", "label": "Edge: low feeling + memory"},
    {"name": "Edge", "tomorrow": "A few times", "excuses": ["I need to plan first"], "feeling": "Sadness or loss", "smokeNow": False, "gender": "male", "converts": True, "objection": "", "country": "India", "label": "Edge: single excuse"},
]

def finish(p, i):
    p["age"] = wpick(["18-24", "25-34", "35-44", "45-54", "55+"], [15, 38, 26, 14, 7])
    p["cigs"] = wpick([3, 5, 8, 10, 15, 20, 30], [8, 16, 18, 24, 16, 12, 6])
    p["years"] = wpick([1, 3, 7, 12, 20, 30], [12, 20, 24, 20, 16, 8])
    names = US_NAMES if p["country"] == "US" else IN_NAMES
    p["name"] = names[i % len(names)]
    if "label" not in p:
        p["label"] = f"Persona {i}"
    return p

for i, e in enumerate(edge):
    personas.append(finish(e, i))

for i in range(45):
    conv = random.random() < 0.32  # review spread; real expected is far lower (skeptical sunk-cost users)
    personas.append(finish({
        "tomorrow": wpick(TOMORROWS, [15, 30, 30, 25]),
        "excuses": rand_excuses(),
        "feeling": wpick(FEELINGS, [22, 26, 16, 14, 12, 10]),
        "smokeNow": random.random() < 0.5,
        "gender": wpick(["male", "female"], [80, 20]),
        "converts": conv,
        "objection": "" if conv else random.choice(OBJECTIONS),
        "country": wpick(["India", "US", "Rest of World"], [85, 12, 3]),
    }, i + 6))


def esc(s):
    return html.escape(s)

rows, total_flags = [], 0
for idx, p in enumerate(personas, 1):
    T = build_transcript(p)
    fl = flags(p)
    total_flags += len(fl)
    turns = []
    for sp, tx in T:
        cls = {"coach": "coach", "user": "user", "note": "note"}[sp]
        who = {"coach": '<span class="who">Coach</span>', "user": '<span class="who">User</span>', "note": ""}[sp]
        turns.append(f'<div class="t {cls}">{who}{esc(tx)}</div>')
    flag_html = ('<div class="flags"><b>⚠ For review:</b><ul>' + "".join(f"<li>{esc(x)}</li>" for x in fl) + "</ul></div>") if fl else ""
    prof = (f'{p["label"]} · {p["name"]} · {p["age"]} · {p["country"]} · {p["cigs"]}/day · {p["years"]}y · '
            f'{p["gender"]} · tomorrows: {p["tomorrow"]} · {len(p["excuses"])} excuses · felt: {p["feeling"]} · '
            f'{"SMOKE" if p["smokeNow"] else "MEMORY"} path · {"CONVERTED" if p["converts"] else "dropped (" + p["objection"] + ")"}')
    rows.append(f'''<details {"open" if idx <= 5 else ""}>
      <summary><span class="pn">#{idx}</span> {esc(prof)} {f'<span class="badge">{len(fl)}⚠</span>' if fl else ''}</summary>
      {flag_html}<div class="chat">{"".join(turns)}</div></details>''')

n_smoke = sum(1 for p in personas if p["smokeNow"])
n_conv = sum(1 for p in personas if p["converts"])
n_low = sum(1 for p in personas if p["feeling"] in LOW_FEELINGS)
n_in = sum(1 for p in personas if p["country"] == "India")

doc = f'''<!doctype html><html><head><meta charset="utf-8"><title>QuitSure Discovery V4 — 50-Persona Content Simulation</title>
<style>
body{{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:900px;margin:0 auto;padding:24px;color:#1a2b32;background:#f4f7f8}}
h1{{color:#1d5b68}} .sum{{background:#fff;border:1px solid #d9e2e5;border-radius:12px;padding:16px 20px;margin-bottom:20px;font-size:14px;line-height:1.5}}
.sum b{{color:#1d5b68}}
details{{background:#fff;border:1px solid #d9e2e5;border-radius:12px;margin:10px 0;padding:6px 14px}}
summary{{cursor:pointer;font-size:13px;font-weight:600;padding:8px 0;color:#33474f}}
.pn{{display:inline-block;min-width:34px;color:#1d5b68;font-weight:800}}
.badge{{background:#fde2e1;color:#c0392b;border-radius:10px;padding:1px 8px;font-size:11px;font-weight:700;margin-left:6px}}
.chat{{padding:8px 0 14px}}
.t{{margin:6px 0;padding:9px 12px;border-radius:12px;font-size:14px;line-height:1.45;max-width:88%}}
.t .who{{display:block;font-size:10px;font-weight:700;text-transform:uppercase;opacity:.6;margin-bottom:2px}}
.coach{{background:#eef4f5;border:1px solid #dde8ea}}
.user{{background:#1d5b68;color:#fff;margin-left:auto}} .user .who{{color:#cfe6ec}}
.note{{background:#fff6e6;border:1px dashed #e0c389;color:#7a5a1e;font-style:italic;font-size:13px;max-width:100%}}
.flags{{background:#fff3f2;border:1px solid #f3c6c2;border-radius:10px;padding:8px 14px;margin:6px 0;font-size:13px;color:#8e2c24}}
.flags ul{{margin:6px 0 2px;padding-left:18px}} .flags li{{margin:3px 0}}
</style></head><body>
<h1>QuitSure Discovery V4 — Content-Flow Simulation</h1>
<div class="sum">
<b>Audience modeled:</b> dropped-off QuitSure users (finished onboarding, never started Day 1, already saw the {PRICE['full']} paywall once) who click a <b>remarketing email</b> deep-link. Distributions match the live cohort: ~88% India, 80/20 male/female, age skew 25-34, ~10 cigs/day, procrastinator-heavy "tomorrow" counts.
<br><br>
<b>What this is:</b> {len(personas)} users walked through the live V4 flow with the exact shipped copy + personalization. Each transcript shows every coach screen + the user's answer. Yellow = email-entry context / branch events / the case-file. Red = content risks to review. <i>(Per Ram, 23 Jun: simulate ~50, produce the Q&A file, have the team review the content.)</i>
<br><br>
<b>Coverage:</b> {n_in}/{len(personas)} India · {n_smoke} smoke-path / {len(personas)-n_smoke} memory-path · {n_conv} converted / {len(personas)-n_conv} dropped · {n_low} low-feeling path · all 4 counts, all 6 feelings.
<br><br>
<b>#1 thing to decide (from the flags):</b> the flow currently shows <b>$ pricing to everyone</b>, but ~88% are <b>India</b> and should see <b>₹4,999→₹1,999</b>. Per-country localization is the biggest production gap. (Conversion shown here ~32% is for review spread — real expected conversion from skeptical sunk-cost users is far lower.)
</div>
{"".join(rows)}
</body></html>'''

with open("simulations/discovery_simulation.html", "w", encoding="utf-8") as f:
    f.write(doc)
print(f"Wrote simulations/discovery_simulation.html — {len(personas)} personas ({n_in} India), {total_flags} flags")
