"""
Maps HubSpot properties to ICP scorer input format using PropertyMapping configuration.
"""

from typing import Dict, List, Optional
from artefact_mcp.core.property_mappings import PropertyMapping


class PropertyMapper:
    """Maps HubSpot data to ICP scorer format."""

    def __init__(self, mapping: PropertyMapping):
        self.mapping = mapping

    def map_to_icp_input(self, hubspot_data: Dict, deal_count: int = 0) -> Dict:
        """Convert HubSpot properties to ICP scorer input format.

        Args:
            hubspot_data: Raw HubSpot company data with properties dict.
            deal_count: Number of closed-won deals for this company.

        Returns:
            Dict formatted for ICPScorer.score_company().
        """
        props = hubspot_data.get("properties", {})

        return {
            "company_name": props.get("name", "Unknown"),
            "hubspot_id": hubspot_data.get("id"),

            # Firmographic
            "industry": props.get(self.mapping.industry, ""),
            "annual_revenue": self._safe_float(props.get(self.mapping.annual_revenue)),
            "employee_count": self._safe_int(props.get(self.mapping.employee_count)),
            "geography": props.get(self.mapping.geography_state) or props.get(self.mapping.geography_country, ""),

            # Behavioral - Tech Stack
            "tech_stack": self._parse_tech_stack(props),

            # Behavioral - Growth Signals
            "growth_signals": self._parse_growth_signals(props),

            # Behavioral - Content Engagement
            "content_engagement": self._parse_content_engagement(props),

            # Behavioral - Purchase History
            "purchase_history": self._parse_purchase_history(deal_count),

            # Strategic Fit
            "decision_maker_access": self._parse_strategic_property(
                props, self.mapping.decision_maker_access, "none"
            ),
            "budget_authority": self._parse_strategic_property(
                props, self.mapping.budget_authority, "none"
            ),
            "strategic_alignment": self._parse_strategic_property(
                props, self.mapping.strategic_alignment, "misaligned"
            ),
        }

    def _parse_tech_stack(self, props: Dict) -> List[str]:
        """Parse tech stack from HubSpot property."""
        if not self.mapping.tech_stack:
            return []

        value = props.get(self.mapping.tech_stack, "")
        if not value:
            return []

        # Handle multi-select (semicolon-separated) or JSON array
        if isinstance(value, list):
            return value
        elif isinstance(value, str):
            return [t.strip() for t in value.split(self.mapping.tech_stack_delimiter) if t.strip()]
        return []

    def _parse_growth_signals(self, props: Dict) -> List[str]:
        """Parse growth signals from multiple HubSpot properties."""
        if not self.mapping.growth_signals:
            return []

        signals = []
        for prop_name in self.mapping.growth_signals:
            value = props.get(prop_name)

            # Check if property has a value (boolean, count > 0, or non-empty string)
            if value:
                if isinstance(value, bool) and value:
                    signals.append(self._signal_name_from_property(prop_name))
                elif isinstance(value, (int, float)) and value > 0:
                    signals.append(self._signal_name_from_property(prop_name))
                elif isinstance(value, str) and value.lower() not in ("no", "none", "false", ""):
                    signals.append(self._signal_name_from_property(prop_name))

        return signals

    def _signal_name_from_property(self, prop_name: str) -> str:
        """Convert property name to human-readable signal name."""
        # Check if custom mapping exists
        if prop_name in self.mapping.growth_signal_keywords:
            return self.mapping.growth_signal_keywords[prop_name]

        # Otherwise infer from property name
        mapping = {
            "linkedin_job_postings": "hiring",
            "recent_funding": "funding",
            "press_mentions": "press",
            "new_office": "expansion",
            "product_launch": "product_launch",
        }
        for key, signal in mapping.items():
            if key in prop_name.lower():
                return signal

        return prop_name  # Fallback to property name

    def _parse_content_engagement(self, props: Dict) -> str:
        """Parse content engagement level."""
        if not self.mapping.content_engagement:
            return "none"

        value = props.get(self.mapping.content_engagement)
        if value is None:
            return "none"

        # Convert to integer
        try:
            count = int(value)
        except (ValueError, TypeError):
            return "none"

        # Apply thresholds
        if count >= self.mapping.content_engagement_thresholds["active"]:
            return "active"
        elif count >= self.mapping.content_engagement_thresholds["occasional"]:
            return "occasional"
        else:
            return "none"

    def _parse_purchase_history(self, deal_count: int) -> str:
        """Classify purchase history based on deal count."""
        if deal_count >= self.mapping.purchase_history_deal_count_threshold["regular"]:
            return "regular"
        elif deal_count >= self.mapping.purchase_history_deal_count_threshold["occasional"]:
            return "occasional"
        else:
            return "never"

    def _parse_strategic_property(self, props: Dict, prop_name: Optional[str], default: str) -> str:
        """Parse a strategic fit property."""
        if not prop_name:
            return default

        value = props.get(prop_name, "")
        if not value:
            return default

        return str(value).lower().replace(" ", "_")

    def _safe_float(self, value) -> Optional[float]:
        """Safely convert to float."""
        if not value:
            return None
        try:
            return float(value)
        except (ValueError, TypeError):
            return None

    def _safe_int(self, value) -> Optional[int]:
        """Safely convert to int."""
        if not value:
            return None
        try:
            return int(value)
        except (ValueError, TypeError):
            return None
