"""Generate deterministic synthetic journal entries for testing."""

from __future__ import annotations

import argparse
import json
import random
from datetime import datetime, timedelta
from pathlib import Path

from cognitive_signal.models.types import JournalEntry

DEFAULT_START_DATE = datetime(2025, 1, 1, 9, 0, 0)
DEFAULT_SEED = 42
NOISE_PROBABILITY = 0.35
BORROW_ADJACENT_PROBABILITY = 0.30

LEXICON = {
    "work_event": [
        "team meeting",
        "planning session",
        "project kickoff",
        "client sync",
        "roadmap review",
        "retrospective",
    ],
    "work_push": [
        "pushed back on the deadline",
        "reframed the scope",
        "asked for clearer ownership",
        "challenged vague assumptions",
        "negotiated a safer timeline",
    ],
    "work_outcome": [
        "a practical plan",
        "clearer roles",
        "shared momentum",
        "more trust",
        "a tighter brief",
    ],
    "work_win": [
        "closed a blocker",
        "unblocked the integration",
        "clarified priorities",
        "landed a tough decision",
        "got alignment from leadership",
    ],
    "work_boundary": [
        "set a boundary around unrealistic asks",
        "asked for breathing room",
        "protected the team's focus",
        "named what was not feasible",
        "redirected the conversation toward priorities",
    ],
    "work_recovery": [
        "take ten quiet minutes",
        "write tomorrow's priorities",
        "decompress with a short walk",
        "shut my laptop on time",
        "reset before the evening",
    ],
    "person_name": ["Sarah", "Maya", "Alex", "Jordan", "Priya", "Daniel"],
    "relationship_tone": [
        "careful but sincere",
        "a little fragile",
        "unexpectedly warm",
        "more open than last week",
        "messy but real",
    ],
    "social_feeling": [
        "relieved",
        "seen",
        "uncertain but hopeful",
        "less alone",
        "surprisingly calm",
    ],
    "reflection_practice": [
        "silence",
        "prayer",
        "breathwork",
        "meditation",
        "journaling",
    ],
    "meaning_word": [
        "purpose",
        "meaning",
        "calling",
        "alignment",
        "integrity",
    ],
    "ordinary_image": [
        "morning light",
        "a warm cup of tea",
        "a quiet room",
        "the sound of rain",
        "an unhurried evening",
    ],
}

WORK_TEMPLATES = [
    "I led the {work_event} today and {work_push} when the timeline got tight.",
    "Most of my attention stayed on execution, and I liked having that clarity.",
    "I mapped the next sprint with the team, and we left with {work_outcome}.",
    "A small win came through when I {work_win}, which lifted the room.",
    "I kept my tone steady in a tense discussion and {work_boundary}.",
    "I still felt a little worn out, but I chose to {work_recovery} before dinner.",
    "The day was busy, but I felt capable and direct in how I handled it.",
]

RELATIONSHIP_TEMPLATES = [
    "Been thinking about what {person_name} said, and it stayed with me all afternoon.",
    "I noticed how quickly I read into pauses, then tried to ask instead of assume.",
    "Our conversation felt {relationship_tone}, and I wanted repair more than control.",
    "I texted {person_name} to check in, and their response made me feel {social_feeling}.",
    "Part of me wanted certainty, but I mostly listened and let the moment breathe.",
    "I kept replaying one sentence and wondering what I missed underneath it.",
    "Friends reminded me that connection takes patience, not perfect timing.",
]

REFLECTIVE_TEMPLATES = [
    "I sat in {reflection_practice} today, wondering about {meaning_word} and what I keep avoiding.",
    "My mind drifted toward gratitude and the question of who I am becoming.",
    "I wrote about the gap between achievement and meaning, and it felt honest.",
    "There was less urgency to act and more curiosity about what this season is teaching me.",
    "I slowed down enough to notice my fear without trying to fix it immediately.",
    "I kept returning to {ordinary_image}, and the ordinary felt quietly sacred.",
    "Action felt less important than attention, so I let the evening stay simple.",
]

NEUTRAL_TEMPLATES = [
    "I took a long walk after lunch and noticed the weather shifting.",
    "I cooked something simple tonight and cleaned the kitchen before bed.",
    "I slept better than expected and woke up a little clearer.",
    "I spent an hour reading and let my phone stay in another room.",
    "I handled errands in the afternoon and finally answered a few emails.",
]

PHASE_TEMPLATES = {
    0: WORK_TEMPLATES,
    1: RELATIONSHIP_TEMPLATES,
    2: REFLECTIVE_TEMPLATES,
}


def _phase_for_day(day_index: int) -> int:
    if day_index < 20:
        return 0
    if day_index < 40:
        return 1
    return 2


def _adjacent_phase(phase: int, rng: random.Random) -> int:
    if phase == 0:
        return 1
    if phase == 2:
        return 1
    return rng.choice([0, 2])


def _render_template(template: str, rng: random.Random) -> str:
    values = {key: rng.choice(options) for key, options in LEXICON.items()}
    return template.format(**values)


def _build_entry_text(day_index: int, rng: random.Random) -> str:
    phase = _phase_for_day(day_index)
    sentence_count = rng.randint(3, 8)

    injected_sentences: list[str] = []
    if rng.random() < NOISE_PROBABILITY:
        noisy_pool = NEUTRAL_TEMPLATES + PHASE_TEMPLATES[_adjacent_phase(phase, rng)]
        injected_sentences.append(_render_template(rng.choice(noisy_pool), rng))

    if rng.random() < BORROW_ADJACENT_PROBABILITY:
        adjacent_pool = PHASE_TEMPLATES[_adjacent_phase(phase, rng)]
        injected_sentences.append(_render_template(rng.choice(adjacent_pool), rng))

    if len(injected_sentences) >= sentence_count:
        injected_sentences = injected_sentences[: max(1, sentence_count - 1)]

    base_sentence_count = sentence_count - len(injected_sentences)
    sentences = [
        _render_template(rng.choice(PHASE_TEMPLATES[phase]), rng)
        for _ in range(base_sentence_count)
    ]
    sentences.extend(injected_sentences)
    rng.shuffle(sentences)
    return " ".join(sentences)


def generate_synthetic_entries(
    num_entries: int = 60,
    start_date: datetime = DEFAULT_START_DATE,
    seed: int = DEFAULT_SEED,
) -> list[JournalEntry]:
    """Generate deterministic synthetic journal entries."""
    rng = random.Random(seed)
    entries: list[JournalEntry] = []

    for index in range(num_entries):
        entries.append(
            JournalEntry(
                text=_build_entry_text(index, rng),
                timestamp=start_date + timedelta(days=index),
                entry_id=f"entry_{index + 1:03d}",
            )
        )
    return entries


def save_entries_jsonl(entries: list[JournalEntry], output_path: Path) -> None:
    """Save entries as JSONL."""
    output_path.parent.mkdir(parents=True, exist_ok=True)
    with output_path.open("w", encoding="utf-8") as handle:
        for entry in entries:
            payload = {
                "entry_id": entry.entry_id,
                "timestamp": entry.timestamp.isoformat(),
                "text": entry.text,
            }
            handle.write(json.dumps(payload, ensure_ascii=True) + "\n")


def _parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Generate synthetic journal entries for testing."
    )
    parser.add_argument(
        "--output",
        type=Path,
        default=Path(__file__).resolve().parent / "synthetic_entries.jsonl",
        help="Path to the output JSONL file.",
    )
    parser.add_argument(
        "--num-entries",
        type=int,
        default=60,
        help="Number of synthetic entries to generate.",
    )
    parser.add_argument(
        "--seed",
        type=int,
        default=DEFAULT_SEED,
        help="Random seed for deterministic output.",
    )
    return parser.parse_args()


def main() -> None:
    args = _parse_args()
    entries = generate_synthetic_entries(
        num_entries=args.num_entries, start_date=DEFAULT_START_DATE, seed=args.seed
    )
    save_entries_jsonl(entries, args.output)


if __name__ == "__main__":
    main()
