"""
Pattern Recognizer - Phase 3 Stories 23-34
===========================================
Deep pattern recognition for philosophy, evolution, and innovation.

Stories:
- 23: Theme Evolution Tracker
- 24: Recurring Thread Detector
- 25: Philosophy Statement Extractor
- 26: Learning Loop Analyzer
- 27: Vision Statement Synthesizer
- 28: Innovation Pattern Recognizer
- 29: Strategic Pivot Detector
- 30: Questioning Spirit Profiler
- 31: Failure Mode Cataloger
- 32: Success Pattern Cataloger
- 33: Collaboration Style Analyzer
- 34: Priority Evolution Tracker
"""

import json
import re
from pathlib import Path
from datetime import datetime
from typing import List, Dict, Any, Tuple, Optional
from dataclasses import dataclass, field, asdict
from collections import defaultdict, Counter
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("pattern_recognizer")

# =============================================================================
# PATHS
# =============================================================================

OUTPUT_BASE = Path("/mnt/e/genesis-system/KNOWLEDGE_GRAPH/creator_mind")
ARCHIVE_PATH = OUTPUT_BASE / "conversations_archive.jsonl"
ANALYSIS_PATH = OUTPUT_BASE / "analysis/conversation_analyses.jsonl"
PATTERNS_DIR = OUTPUT_BASE / "patterns"
EVOLUTION_DIR = OUTPUT_BASE / "evolution"
PHILOSOPHY_DIR = OUTPUT_BASE / "philosophy"
PHILOSOPHY_DIR.mkdir(exist_ok=True)

# =============================================================================
# STORY 25: Philosophy Patterns
# =============================================================================

PHILOSOPHY_PATTERNS = [
    # Core beliefs
    (r"i (?:truly |really |deeply )?believe\s+(?:that\s+)?(.{20,200})", "belief"),
    (r"my (?:core |fundamental )?belief is\s+(?:that\s+)?(.{20,200})", "belief"),
    (r"i'm convinced\s+(?:that\s+)?(.{20,200})", "belief"),

    # Values
    (r"(?:what )?matters (?:most )?(?:to me )?is\s+(.{20,150})", "value"),
    (r"i value\s+(.{10,100})", "value"),
    (r"(?:it's |is )?important (?:to me )?that\s+(.{20,150})", "value"),

    # Principles
    (r"my (?:guiding )?principle is\s+(.{20,150})", "principle"),
    (r"i always\s+(.{20,100})", "principle"),
    (r"(?:the )?rule (?:i follow |is )\s*:?\s*(.{20,150})", "principle"),

    # Worldview
    (r"the way i see (?:it|the world|things)\s*,?\s*(.{20,200})", "worldview"),
    (r"(?:in )?my (?:view|opinion|perspective)\s*,?\s*(.{20,200})", "worldview"),
    (r"i think (?:that )?the (?:key|secret|truth) is\s+(.{20,200})", "worldview"),
]

# =============================================================================
# STORY 27: Vision Patterns
# =============================================================================

VISION_PATTERNS = [
    (r"(?:my |the )?vision (?:is |for ).{0,20}(.{20,200})", "vision"),
    (r"(?:i |we )?want to (?:build|create|achieve)\s+(.{20,200})", "aspiration"),
    (r"(?:the )?goal is (?:to )?\s*(.{20,200})", "goal"),
    (r"(?:i'm |we're )?working towards?\s+(.{20,150})", "goal"),
    (r"(?:the )?mission is\s+(.{20,200})", "mission"),
    (r"(?:i |we )?dream of\s+(.{20,150})", "aspiration"),
    (r"(?:imagine |picture )?a (?:world|future) where\s+(.{20,200})", "vision"),
    (r"genesis (?:is|will be|should be)\s+(.{20,200})", "genesis_vision"),
    (r"aiva (?:is|will be|should be)\s+(.{20,200})", "aiva_vision"),
]

# =============================================================================
# STORY 28: Innovation Patterns
# =============================================================================

INNOVATION_PATTERNS = [
    (r"(?:what if|imagine if) we\s+(.{20,200})", "hypothesis"),
    (r"(?:i just )?(?:realized|discovered|figured out)\s+(?:that\s+)?(.{20,200})", "insight"),
    (r"(?:the |a )?breakthrough (?:is|was)\s+(.{20,200})", "breakthrough"),
    (r"(?:nobody|no one) (?:is|has)\s+(.{20,150})", "opportunity"),
    (r"(?:we could |we can )combine\s+(.{20,150})", "synthesis"),
    (r"(?:a )?new (?:approach|way|method)\s*:?\s*(.{20,150})", "innovation"),
    (r"(?:this is |here's )?(?:the |a )?game.?changer\s*:?\s*(.{20,150})?", "breakthrough"),
]

# =============================================================================
# STORY 29: Pivot Patterns
# =============================================================================

PIVOT_PATTERNS = [
    (r"(?:i |we )?(?:used to|previously) (?:think|believe)\s+(.{20,150})", "before"),
    (r"(?:but )?now i (?:think|believe|realize)\s+(.{20,150})", "after"),
    (r"(?:i |we )?changed (?:my|our) (?:mind|approach|strategy)\s+(.{20,150})?", "pivot"),
    (r"(?:i |we )?(?:was|were) wrong about\s+(.{20,150})", "correction"),
    (r"(?:actually|in fact),?\s+(.{20,150})", "realization"),
    (r"(?:i |we )?pivot(?:ed|ing)? (?:to|from|towards?)\s+(.{20,150})", "pivot"),
]

# =============================================================================
# STORY 30: Questioning Patterns
# =============================================================================

QUESTION_TYPES = {
    'strategic': [r'(?:should we|how do we|what\'s the best way to)\s+(.{20,150})\?'],
    'exploratory': [r'(?:what if|what about|have you considered)\s+(.{20,150})\?'],
    'debugging': [r'(?:why (?:is|does|doesn\'t)|what\'s (?:wrong|happening))\s+(.{20,150})\?'],
    'clarifying': [r'(?:what do you mean|can you explain|how does)\s+(.{20,150})\?'],
    'philosophical': [r'(?:what is the (?:point|purpose|meaning)|why do we)\s+(.{20,150})\?'],
    'socratic': [r'(?:but then|if that\'s true|doesn\'t that mean)\s+(.{20,150})\?'],
}

# =============================================================================
# STORY 31: Failure Patterns
# =============================================================================

FAILURE_PATTERNS = [
    (r"(?:that |this )?(?:didn't|doesn't|won't) work\s*(?:because\s+)?(.{0,150})", "failure"),
    (r"(?:i |we )?failed (?:to |at )\s*(.{20,150})", "failure"),
    (r"(?:the )?mistake (?:was|i made)\s+(.{20,150})", "mistake"),
    (r"(?:i |we )?(?:should|shouldn't) have\s+(.{20,150})", "regret"),
    (r"(?:the )?(?:problem|issue) (?:was|is)\s+(.{20,150})", "problem"),
    (r"(?:i |we )?wasted (?:time|money|effort) on\s+(.{20,150})", "waste"),
    (r"(?:lesson learned|i learned)\s*:?\s*(.{20,150})", "lesson"),
]

# =============================================================================
# STORY 32: Success Patterns
# =============================================================================

SUCCESS_PATTERNS = [
    (r"(?:that |this )?worked (?:because|when)\s+(.{20,150})", "success"),
    (r"(?:the )?(?:key|secret) (?:was|is|to)\s+(.{20,150})", "insight"),
    (r"(?:what|this) made (?:it|the difference)\s+(.{20,150})?", "differentiator"),
    (r"(?:i |we )?finally\s+(.{20,150})", "breakthrough"),
    (r"(?:the )?winning (?:strategy|approach|formula)\s*:?\s*(.{20,150})", "strategy"),
    (r"(?:this |it )?(?:is|was) (?:exactly|precisely) what\s+(.{20,150})", "fit"),
]

# =============================================================================
# DATA STRUCTURES
# =============================================================================

@dataclass
class PhilosophyStatement:
    """A philosophical statement from Kinan"""
    id: str
    statement: str
    type: str  # belief, value, principle, worldview
    context: str
    timestamp: str
    source_conversation: str
    confidence: float = 0.5

@dataclass
class VisionStatement:
    """A vision/aspiration statement"""
    id: str
    statement: str
    type: str  # vision, goal, mission, aspiration
    domain: str  # genesis, aiva, business, personal
    timestamp: str
    source_conversation: str

@dataclass
class InnovationMoment:
    """An innovation or insight moment"""
    id: str
    description: str
    type: str  # hypothesis, insight, breakthrough, synthesis
    related_topics: List[str]
    timestamp: str
    source_conversation: str

@dataclass
class StrategicPivot:
    """A strategic pivot or change in thinking"""
    id: str
    before: str
    after: str
    trigger: str
    domain: str
    pivot_date: str
    source_conversations: List[str]

@dataclass
class FailurePattern:
    """A failure or mistake pattern"""
    id: str
    description: str
    type: str
    lesson_learned: str
    frequency: int
    domains: List[str]
    source_conversations: List[str]

@dataclass
class SuccessPattern:
    """A success pattern"""
    id: str
    description: str
    type: str
    enabling_factors: List[str]
    frequency: int
    domains: List[str]
    source_conversations: List[str]

@dataclass
class QuestioningProfile:
    """Profile of questioning style"""
    question_types: Dict[str, int]
    depth_preference: str  # surface, moderate, deep
    favorite_domains: List[str]
    socratic_tendency: float
    sample_questions: Dict[str, List[str]]

@dataclass
class ThemeEvolution:
    """Evolution of a theme over time"""
    theme: str
    first_mention: str
    last_mention: str
    peak_month: str
    total_mentions: int
    monthly_trajectory: Dict[str, int]
    status: str  # emerging, stable, declining, abandoned

# =============================================================================
# MAIN RECOGNIZER
# =============================================================================

class PatternRecognizer:
    """Phase 3: Pattern recognition and philosophy extraction"""

    def __init__(self):
        self.philosophies: List[PhilosophyStatement] = []
        self.visions: List[VisionStatement] = []
        self.innovations: List[InnovationMoment] = []
        self.pivots: List[StrategicPivot] = []
        self.failures: Dict[str, FailurePattern] = {}
        self.successes: Dict[str, SuccessPattern] = {}
        self.theme_evolution: Dict[str, ThemeEvolution] = {}
        self.question_profile = QuestioningProfile(
            question_types=defaultdict(int),
            depth_preference="",
            favorite_domains=[],
            socratic_tendency=0.0,
            sample_questions=defaultdict(list)
        )

        # Load conversation analyses for topic info
        self.analyses = {}
        self._load_analyses()

        # Compile patterns
        self.philosophy_compiled = [(re.compile(p, re.IGNORECASE), t) for p, t in PHILOSOPHY_PATTERNS]
        self.vision_compiled = [(re.compile(p, re.IGNORECASE), t) for p, t in VISION_PATTERNS]
        self.innovation_compiled = [(re.compile(p, re.IGNORECASE), t) for p, t in INNOVATION_PATTERNS]
        self.pivot_compiled = [(re.compile(p, re.IGNORECASE), t) for p, t in PIVOT_PATTERNS]
        self.failure_compiled = [(re.compile(p, re.IGNORECASE), t) for p, t in FAILURE_PATTERNS]
        self.success_compiled = [(re.compile(p, re.IGNORECASE), t) for p, t in SUCCESS_PATTERNS]
        self.question_compiled = {
            qtype: [re.compile(p, re.IGNORECASE) for p in patterns]
            for qtype, patterns in QUESTION_TYPES.items()
        }

    def _load_analyses(self):
        """Load previous conversation analyses"""
        if ANALYSIS_PATH.exists():
            with open(ANALYSIS_PATH) as f:
                for line in f:
                    data = json.loads(line)
                    self.analyses[data['uuid']] = data

    # =========================================================================
    # STORY 23: Theme Evolution
    # =========================================================================

    def track_theme_evolution(self, conversations: List[Dict]):
        """Track how themes evolve over time"""
        theme_timeline = defaultdict(lambda: defaultdict(int))
        theme_first_last = defaultdict(lambda: {'first': None, 'last': None})

        for conv in sorted(conversations, key=lambda x: x.get('created_at', '')):
            uuid = conv['uuid']
            timestamp = conv.get('created_at', '')
            month = timestamp[:7] if timestamp else 'unknown'

            # Get topics from analysis
            if uuid in self.analyses:
                topics = self.analyses[uuid].get('topics', {})
                for topic in topics:
                    theme_timeline[topic][month] += 1
                    if theme_first_last[topic]['first'] is None:
                        theme_first_last[topic]['first'] = timestamp
                    theme_first_last[topic]['last'] = timestamp

        # Create evolution objects
        for theme, monthly in theme_timeline.items():
            total = sum(monthly.values())
            peak_month = max(monthly, key=monthly.get) if monthly else ""

            # Determine status
            months = sorted(monthly.keys())
            if len(months) >= 2:
                recent = sum(monthly.get(m, 0) for m in months[-2:])
                early = sum(monthly.get(m, 0) for m in months[:2])
                if recent > early * 1.5:
                    status = "emerging"
                elif recent < early * 0.5:
                    status = "declining"
                else:
                    status = "stable"
            else:
                status = "new"

            self.theme_evolution[theme] = ThemeEvolution(
                theme=theme,
                first_mention=theme_first_last[theme]['first'] or "",
                last_mention=theme_first_last[theme]['last'] or "",
                peak_month=peak_month,
                total_mentions=total,
                monthly_trajectory=dict(monthly),
                status=status
            )

    # =========================================================================
    # STORY 25: Philosophy Extraction
    # =========================================================================

    def extract_philosophy(self, text: str, conv_uuid: str, timestamp: str, context: str = ""):
        """Extract philosophical statements"""
        for pattern, ptype in self.philosophy_compiled:
            matches = pattern.findall(text)
            for match in matches:
                if len(match) > 20:
                    self.philosophies.append(PhilosophyStatement(
                        id=f"phil_{len(self.philosophies)+1:04d}",
                        statement=match.strip()[:200],
                        type=ptype,
                        context=context[:300],
                        timestamp=timestamp,
                        source_conversation=conv_uuid
                    ))

    # =========================================================================
    # STORY 27: Vision Synthesis
    # =========================================================================

    def extract_vision(self, text: str, conv_uuid: str, timestamp: str):
        """Extract vision statements"""
        for pattern, vtype in self.vision_compiled:
            matches = pattern.findall(text)
            for match in matches:
                if len(match) > 20:
                    # Determine domain
                    domain = "general"
                    if "genesis" in text.lower():
                        domain = "genesis"
                    elif "aiva" in text.lower():
                        domain = "aiva"
                    elif any(w in text.lower() for w in ['revenue', 'business', 'client', 'money']):
                        domain = "business"

                    self.visions.append(VisionStatement(
                        id=f"vision_{len(self.visions)+1:04d}",
                        statement=match.strip()[:200],
                        type=vtype,
                        domain=domain,
                        timestamp=timestamp,
                        source_conversation=conv_uuid
                    ))

    # =========================================================================
    # STORY 28: Innovation Detection
    # =========================================================================

    def detect_innovation(self, text: str, conv_uuid: str, timestamp: str, topics: List[str]):
        """Detect innovation moments"""
        for pattern, itype in self.innovation_compiled:
            matches = pattern.findall(text)
            for match in matches:
                if match and len(match) > 15:
                    self.innovations.append(InnovationMoment(
                        id=f"innov_{len(self.innovations)+1:04d}",
                        description=match.strip()[:200] if match else "",
                        type=itype,
                        related_topics=topics[:5],
                        timestamp=timestamp,
                        source_conversation=conv_uuid
                    ))

    # =========================================================================
    # STORY 29: Pivot Detection
    # =========================================================================

    def detect_pivots(self, text: str, conv_uuid: str, timestamp: str):
        """Detect strategic pivots"""
        before_matches = []
        after_matches = []
        pivot_matches = []

        for pattern, ptype in self.pivot_compiled:
            matches = pattern.findall(text)
            for match in matches:
                if match:
                    if ptype == "before":
                        before_matches.append(match)
                    elif ptype == "after":
                        after_matches.append(match)
                    else:
                        pivot_matches.append(match)

        # Create pivot records
        if before_matches and after_matches:
            self.pivots.append(StrategicPivot(
                id=f"pivot_{len(self.pivots)+1:04d}",
                before=before_matches[0][:150],
                after=after_matches[0][:150],
                trigger="",
                domain="general",
                pivot_date=timestamp,
                source_conversations=[conv_uuid]
            ))

        for match in pivot_matches:
            self.pivots.append(StrategicPivot(
                id=f"pivot_{len(self.pivots)+1:04d}",
                before="",
                after=match[:150] if match else "",
                trigger="explicit pivot",
                domain="general",
                pivot_date=timestamp,
                source_conversations=[conv_uuid]
            ))

    # =========================================================================
    # STORY 30: Questioning Profile
    # =========================================================================

    def analyze_questions(self, text: str):
        """Analyze questioning patterns"""
        for qtype, patterns in self.question_compiled.items():
            for pattern in patterns:
                matches = pattern.findall(text)
                self.question_profile.question_types[qtype] += len(matches)

                # Store samples
                for match in matches[:3]:
                    if len(self.question_profile.sample_questions[qtype]) < 10:
                        self.question_profile.sample_questions[qtype].append(match[:100])

    # =========================================================================
    # STORY 31: Failure Cataloging
    # =========================================================================

    def catalog_failures(self, text: str, conv_uuid: str, topics: List[str]):
        """Catalog failure patterns"""
        for pattern, ftype in self.failure_compiled:
            matches = pattern.findall(text)
            for match in matches:
                if match and len(match) > 10:
                    key = match[:50].lower()
                    if key not in self.failures:
                        self.failures[key] = FailurePattern(
                            id=f"fail_{len(self.failures)+1:04d}",
                            description=match[:150],
                            type=ftype,
                            lesson_learned="",
                            frequency=1,
                            domains=topics[:3],
                            source_conversations=[conv_uuid]
                        )
                    else:
                        self.failures[key].frequency += 1
                        if conv_uuid not in self.failures[key].source_conversations:
                            self.failures[key].source_conversations.append(conv_uuid)

    # =========================================================================
    # STORY 32: Success Cataloging
    # =========================================================================

    def catalog_successes(self, text: str, conv_uuid: str, topics: List[str]):
        """Catalog success patterns"""
        for pattern, stype in self.success_compiled:
            matches = pattern.findall(text)
            for match in matches:
                if match and len(match) > 10:
                    key = match[:50].lower()
                    if key not in self.successes:
                        self.successes[key] = SuccessPattern(
                            id=f"success_{len(self.successes)+1:04d}",
                            description=match[:150],
                            type=stype,
                            enabling_factors=[],
                            frequency=1,
                            domains=topics[:3],
                            source_conversations=[conv_uuid]
                        )
                    else:
                        self.successes[key].frequency += 1
                        if conv_uuid not in self.successes[key].source_conversations:
                            self.successes[key].source_conversations.append(conv_uuid)

    # =========================================================================
    # STORY 33: Collaboration Style
    # =========================================================================

    def analyze_collaboration_style(self, conversations: List[Dict]) -> Dict[str, Any]:
        """Analyze how Kinan collaborates with AI"""
        style = {
            'delegation_patterns': Counter(),
            'feedback_style': Counter(),
            'iteration_count': 0,
            'average_turns': 0,
            'preferred_interaction': '',
        }

        delegation_patterns = [
            (r'(?:can you|please|could you)\s+(.{10,50})', 'polite_request'),
            (r'(?:do this|make this|implement)', 'direct_command'),
            (r'(?:what do you think|your thoughts|suggest)', 'collaborative'),
            (r'(?:i\'ll do|let me|i\'m going to)', 'self_directed'),
        ]

        feedback_patterns = [
            (r'(?:perfect|exactly|great job|well done)', 'positive'),
            (r'(?:not quite|wrong|incorrect|no)', 'corrective'),
            (r'(?:close but|almost|needs)', 'iterative'),
        ]

        total_turns = 0
        for conv in conversations:
            messages = conv.get('messages', [])
            total_turns += len(messages)

            for msg in messages:
                if msg.get('sender') != 'human':
                    continue
                text = msg.get('text', '')

                for pattern, dtype in delegation_patterns:
                    if re.search(pattern, text, re.IGNORECASE):
                        style['delegation_patterns'][dtype] += 1

                for pattern, ftype in feedback_patterns:
                    if re.search(pattern, text, re.IGNORECASE):
                        style['feedback_style'][ftype] += 1

        style['average_turns'] = total_turns / len(conversations) if conversations else 0
        style['delegation_patterns'] = dict(style['delegation_patterns'])
        style['feedback_style'] = dict(style['feedback_style'])

        # Determine preferred style
        if style['delegation_patterns']:
            style['preferred_interaction'] = max(style['delegation_patterns'],
                                                  key=style['delegation_patterns'].get)

        return style

    # =========================================================================
    # MAIN PIPELINE
    # =========================================================================

    def process_conversation(self, conv: Dict):
        """Process a single conversation for patterns"""
        uuid = conv['uuid']
        timestamp = conv.get('created_at', '')
        messages = conv.get('messages', [])

        # Get topics from analysis
        topics = list(self.analyses.get(uuid, {}).get('topics', {}).keys())

        # Combine human text
        human_text = ' '.join([
            m.get('text', '') for m in messages
            if m.get('sender') == 'human'
        ])

        # Run all extractors
        self.extract_philosophy(human_text, uuid, timestamp, conv.get('name', ''))
        self.extract_vision(human_text, uuid, timestamp)
        self.detect_innovation(human_text, uuid, timestamp, topics)
        self.detect_pivots(human_text, uuid, timestamp)
        self.analyze_questions(human_text)
        self.catalog_failures(human_text, uuid, topics)
        self.catalog_successes(human_text, uuid, topics)

    def run(self):
        """Execute full pattern recognition"""
        logger.info("=" * 60)
        logger.info("PHASE 3: PATTERN RECOGNITION")
        logger.info("Stories 23-34")
        logger.info("=" * 60)

        # Load conversations
        conversations = []
        with open(ARCHIVE_PATH) as f:
            for line in f:
                conversations.append(json.loads(line))

        logger.info(f"Loaded {len(conversations)} conversations")

        # Story 23: Theme Evolution
        logger.info("Story 23: Tracking theme evolution...")
        self.track_theme_evolution(conversations)

        # Process each conversation
        for i, conv in enumerate(conversations):
            self.process_conversation(conv)
            if (i + 1) % 100 == 0:
                logger.info(f"Processed {i+1} conversations")

        # Story 33: Collaboration style
        logger.info("Story 33: Analyzing collaboration style...")
        collab_style = self.analyze_collaboration_style(conversations)

        # Finalize question profile
        total_questions = sum(self.question_profile.question_types.values())
        socratic = self.question_profile.question_types.get('socratic', 0)
        self.question_profile.socratic_tendency = socratic / total_questions if total_questions else 0

        # Determine depth preference
        strategic = self.question_profile.question_types.get('strategic', 0)
        philosophical = self.question_profile.question_types.get('philosophical', 0)
        if philosophical + strategic > total_questions * 0.3:
            self.question_profile.depth_preference = "deep"
        elif philosophical + strategic > total_questions * 0.15:
            self.question_profile.depth_preference = "moderate"
        else:
            self.question_profile.depth_preference = "surface"

        # Save results
        self.save_results(collab_style)
        self.generate_report(collab_style)

    def save_results(self, collab_style: Dict):
        """Save all pattern recognition results"""

        # Philosophy statements
        with open(PHILOSOPHY_DIR / "philosophy_statements.jsonl", 'w') as f:
            for phil in self.philosophies:
                f.write(json.dumps(asdict(phil)) + '\n')

        # Vision statements
        with open(PHILOSOPHY_DIR / "vision_statements.jsonl", 'w') as f:
            for vision in self.visions:
                f.write(json.dumps(asdict(vision)) + '\n')

        # Innovations
        with open(PHILOSOPHY_DIR / "innovation_moments.jsonl", 'w') as f:
            for innov in self.innovations:
                f.write(json.dumps(asdict(innov)) + '\n')

        # Pivots
        with open(EVOLUTION_DIR / "strategic_pivots.jsonl", 'w') as f:
            for pivot in self.pivots:
                f.write(json.dumps(asdict(pivot)) + '\n')

        # Theme evolution
        with open(EVOLUTION_DIR / "theme_evolution.jsonl", 'w') as f:
            for theme in self.theme_evolution.values():
                f.write(json.dumps(asdict(theme)) + '\n')

        # Failures
        with open(PATTERNS_DIR / "failure_patterns.jsonl", 'w') as f:
            for fail in sorted(self.failures.values(), key=lambda x: x.frequency, reverse=True):
                f.write(json.dumps(asdict(fail)) + '\n')

        # Successes
        with open(PATTERNS_DIR / "success_patterns.jsonl", 'w') as f:
            for success in sorted(self.successes.values(), key=lambda x: x.frequency, reverse=True):
                f.write(json.dumps(asdict(success)) + '\n')

        # Questioning profile
        with open(PHILOSOPHY_DIR / "questioning_profile.json", 'w') as f:
            profile = {
                'question_types': dict(self.question_profile.question_types),
                'depth_preference': self.question_profile.depth_preference,
                'socratic_tendency': self.question_profile.socratic_tendency,
                'sample_questions': {k: list(v) for k, v in self.question_profile.sample_questions.items()}
            }
            json.dump(profile, f, indent=2)

        # Collaboration style
        with open(PHILOSOPHY_DIR / "collaboration_style.json", 'w') as f:
            json.dump(collab_style, f, indent=2)

        logger.info("Results saved!")

    def generate_report(self, collab_style: Dict):
        """Generate summary report"""
        logger.info("\n" + "=" * 60)
        logger.info("PATTERN RECOGNITION REPORT")
        logger.info("=" * 60)

        logger.info(f"\n--- Story 23: THEME EVOLUTION ---")
        emerging = [t for t in self.theme_evolution.values() if t.status == "emerging"]
        declining = [t for t in self.theme_evolution.values() if t.status == "declining"]
        logger.info(f"Themes tracked: {len(self.theme_evolution)}")
        logger.info(f"Emerging themes: {[t.theme for t in emerging[:5]]}")
        logger.info(f"Declining themes: {[t.theme for t in declining[:5]]}")

        logger.info(f"\n--- Story 25: PHILOSOPHY STATEMENTS ---")
        logger.info(f"Total statements: {len(self.philosophies)}")
        by_type = Counter(p.type for p in self.philosophies)
        for ptype, count in by_type.most_common():
            logger.info(f"  {ptype}: {count}")

        logger.info(f"\n--- Story 27: VISION STATEMENTS ---")
        logger.info(f"Total visions: {len(self.visions)}")
        by_domain = Counter(v.domain for v in self.visions)
        for domain, count in by_domain.most_common():
            logger.info(f"  {domain}: {count}")

        logger.info(f"\n--- Story 28: INNOVATION MOMENTS ---")
        logger.info(f"Total innovations: {len(self.innovations)}")
        by_type = Counter(i.type for i in self.innovations)
        for itype, count in by_type.most_common():
            logger.info(f"  {itype}: {count}")

        logger.info(f"\n--- Story 29: STRATEGIC PIVOTS ---")
        logger.info(f"Total pivots detected: {len(self.pivots)}")

        logger.info(f"\n--- Story 30: QUESTIONING PROFILE ---")
        logger.info(f"Depth preference: {self.question_profile.depth_preference}")
        logger.info(f"Socratic tendency: {self.question_profile.socratic_tendency:.2%}")
        for qtype, count in sorted(self.question_profile.question_types.items(),
                                    key=lambda x: x[1], reverse=True)[:5]:
            logger.info(f"  {qtype}: {count}")

        logger.info(f"\n--- Story 31: FAILURE PATTERNS ---")
        logger.info(f"Unique failures: {len(self.failures)}")
        top_failures = sorted(self.failures.values(), key=lambda x: x.frequency, reverse=True)[:3]
        for f in top_failures:
            logger.info(f"  [{f.frequency}x] {f.description[:50]}...")

        logger.info(f"\n--- Story 32: SUCCESS PATTERNS ---")
        logger.info(f"Unique successes: {len(self.successes)}")
        top_successes = sorted(self.successes.values(), key=lambda x: x.frequency, reverse=True)[:3]
        for s in top_successes:
            logger.info(f"  [{s.frequency}x] {s.description[:50]}...")

        logger.info(f"\n--- Story 33: COLLABORATION STYLE ---")
        logger.info(f"Preferred interaction: {collab_style.get('preferred_interaction', 'unknown')}")
        logger.info(f"Average turns per conversation: {collab_style.get('average_turns', 0):.1f}")


# =============================================================================
# CLI
# =============================================================================

if __name__ == "__main__":
    recognizer = PatternRecognizer()
    recognizer.run()
