#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary.
"""Decision extractor: detects commitment language and stores decisions."""
import logging
from datetime import datetime, timezone

from pulse.daemons.distiller.extractors.base import BaseExtractor

log = logging.getLogger('pulse.distiller.decisions')

_LLM_MIN_CHARS = 200


class DecisionExtractor(BaseExtractor):
    """Extracts decisions via regex; falls back to LLM for long text with no regex hits."""

    def __init__(self):
        super().__init__('decisions', 'decisions')

    def extract(self, user_text: str, agent_text: str, metadata: dict) -> list:
        """Parse decisions; LLM fallback if regex yields 0 on long text."""
        try:
            from pulse.brain.extraction.decision_parser import parse_decisions
        except ImportError:
            return []

        ts = metadata.get('timestamp', datetime.now(timezone.utc).isoformat())
        source = metadata.get('source', 'distiller')
        domain = metadata.get('domain', 'general')

        try:
            decisions = parse_decisions(user_text, agent_text)
        except Exception as exc:
            log.debug('decision_parser failed: %s', exc)
            decisions = []

        combined = user_text + '\n' + agent_text if agent_text else user_text

        # LLM enhancement: if regex found nothing and text is substantial
        if not decisions and len(combined) > _LLM_MIN_CHARS:
            decisions = self._llm_extract(combined, domain, ts, source)

        for dec in decisions:
            dec.setdefault('_source', source)

        return decisions

    def _llm_extract(self, text: str, domain: str, timestamp: str, source: str) -> list:
        """Use LLM to extract decisions when regex finds none."""
        try:
            from pulse.core.llm_router import dispatch_json
        except ImportError:
            return []

        prompt = (
            'Extract key decisions from this conversation. Return ONLY valid JSON:\n'
            '{"decisions": [{"choice": "...", "reasoning": "...", "domain": "..."}]}\n'
            'Only include genuine commitments ("we chose X", "going with Y"). '
            'Empty array if no clear decisions.\n\n'
            f'CONVERSATION:\n{text[:2500]}'
        )
        try:
            result = dispatch_json(prompt=prompt, task_type='premium')
        except Exception as exc:
            log.debug('LLM decision extraction failed: %s', exc)
            return []

        if not isinstance(result, dict):
            return []

        items = []
        for dec in result.get('decisions', [])[:5]:
            if not isinstance(dec, dict):
                continue
            choice = dec.get('choice', '').strip()
            if not choice or len(choice) < 3:
                continue
            items.append({
                'type': 'decision',
                'choice': choice[:120],
                'reasoning': dec.get('reasoning', '')[:200],
                'domain': dec.get('domain', domain),
                'timestamp': timestamp,
                'confidence': 0.65,
                'extraction_method': 'llm',
                'status': 'active',
            })
        return items

    def write(self, items: list) -> int:
        """Delegate to decision_store which handles dedup and supersession."""
        if not items:
            return 0
        try:
            from pulse.brain.persistence.decision_store import store_decision
        except ImportError:
            return 0

        written = 0
        for item in items:
            clean = {k: v for k, v in item.items() if not k.startswith('_')}
            try:
                if store_decision(clean):
                    written += 1
            except Exception as exc:
                log.debug('store_decision failed: %s', exc)
        self.extracted_count += written
        return written
