"""
Context Service - Manages organization profiles for context-aware matching
"""

from typing import Dict, Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from datetime import datetime
import logging

from ..models import OrgProfile

logger = logging.getLogger(__name__)

# Industry detection patterns
INDUSTRY_PATTERNS = {
    "healthcare_provider": {
        "keywords": [
            "health",
            "medical",
            "hospital",
            "clinic",
            "care",
            "physician",
            "doctor",
        ],
        "domains": ["hca.com", "ascension.org", "kaiserpermanente.org", "mayo.edu"],
        "sub_industries": {
            "hospital_system": ["hospital", "health system", "medical center"],
            "clinic": ["clinic", "urgent care", "family practice"],
            "specialty": ["cardiology", "oncology", "orthopedic"],
        },
    },
    "manufacturing": {
        "keywords": [
            "manufacturing",
            "industrial",
            "factory",
            "production",
            "assembly",
        ],
        "domains": ["ge.com", "3m.com", "honeywell.com", "caterpillar.com"],
        "sub_industries": {
            "automotive": ["automotive", "vehicle", "car", "truck"],
            "aerospace": ["aerospace", "aviation", "aircraft"],
            "industrial": ["industrial", "machinery", "equipment"],
        },
    },
    "software_saas": {
        "keywords": ["software", "saas", "platform", "cloud", "app", "digital"],
        "domains": ["salesforce.com", "microsoft.com", "oracle.com", "adobe.com"],
        "sub_industries": {
            "crm": ["crm", "customer relationship"],
            "erp": ["erp", "enterprise resource"],
            "martech": ["marketing", "advertising", "analytics"],
        },
    },
    "finance": {
        "keywords": ["bank", "financial", "insurance", "investment", "capital"],
        "domains": ["jpmorgan.com", "bankofamerica.com", "wellsfargo.com"],
        "sub_industries": {
            "banking": ["bank", "credit union"],
            "insurance": ["insurance", "underwriting"],
            "investment": ["investment", "asset management", "private equity"],
        },
    },
    "education": {
        "keywords": ["university", "college", "school", "education", "academic"],
        "domains": [".edu"],
        "sub_industries": {
            "higher_ed": ["university", "college"],
            "k12": ["school district", "elementary", "high school"],
            "training": ["training", "certification", "bootcamp"],
        },
    },
}

# Context-based weight adjustments
INDUSTRY_WEIGHTS = {
    "healthcare_provider": {
        "domain": 0.6,  # Shared domains common
        "name": 1.25,  # Facility names critical
        "geo": 1.3,  # Location very important
        "phone": 1.0,
        "identifier": 1.4,  # NPI, HIN critical
    },
    "manufacturing": {
        "domain": 1.2,
        "name": 1.0,
        "geo": 0.8,
        "phone": 1.1,
        "identifier": 1.3,  # DUNS important
    },
    "software_saas": {
        "domain": 1.4,  # Domain very reliable
        "name": 1.1,
        "geo": 0.6,  # Less important
        "phone": 0.9,
        "identifier": 1.0,
    },
    "finance": {
        "domain": 1.3,
        "name": 1.2,
        "geo": 1.0,
        "phone": 1.0,
        "identifier": 1.2,
    },
    "education": {
        "domain": 1.5,  # .edu domains unique
        "name": 1.1,
        "geo": 1.1,
        "phone": 0.8,
        "identifier": 1.0,
    },
}


class ContextService:
    """Service for managing organization context profiles"""

    def __init__(self, db: AsyncSession):
        self.db = db
        self._cache = {}  # Simple in-memory cache

    async def get_or_create_profile(self, account_id: str) -> OrgProfile:
        """Get existing profile or create new one"""
        # Check cache
        if account_id in self._cache:
            return self._cache[account_id]

        # Check database
        result = await self.db.execute(
            select(OrgProfile).where(OrgProfile.account_id == account_id)
        )
        profile = result.scalar_one_or_none()

        if not profile:
            # Create new profile
            profile = OrgProfile(account_id=account_id)
            self.db.add(profile)
            await self.db.commit()
            await self.db.refresh(profile)

        # Cache it
        self._cache[account_id] = profile
        return profile

    async def bootstrap_from_signup(
        self, account_id: str, email: str, company_name: Optional[str] = None
    ) -> OrgProfile:
        """Bootstrap profile from signup information"""
        profile = await self.get_or_create_profile(account_id)

        # Extract domain
        domain = email.split("@")[-1].lower()
        profile.domain = domain
        profile.company_name = company_name

        # Detect industry
        industry_scores = self._detect_industry(domain, company_name)
        if industry_scores:
            best_industry = max(industry_scores.items(), key=lambda x: x[1])
            profile.industry = best_industry[0]
            profile.profile_confidence = best_industry[1]

            # Add evidence
            profile.source_evidence = profile.source_evidence or []
            profile.source_evidence.append(
                {
                    "source": "signup",
                    "field": "domain",
                    "value": domain,
                    "confidence": best_industry[1],
                    "timestamp": datetime.utcnow().isoformat(),
                }
            )

        # Infer sales motion
        if domain.endswith(".edu") or domain.endswith(".gov"):
            profile.sales_motion = "B2B"
            profile.hierarchy_complexity = "high"
        elif any(consumer in domain for consumer in ["gmail", "yahoo", "hotmail"]):
            profile.sales_motion = "B2C"
            profile.hierarchy_complexity = "low"
        else:
            profile.sales_motion = "B2B"  # Default
            profile.hierarchy_complexity = "medium"

        await self.db.commit()
        return profile

    def _detect_industry(
        self, domain: str, company_name: Optional[str] = None
    ) -> Dict[str, float]:
        """Detect likely industry from domain and company name"""
        scores = {}

        for industry, patterns in INDUSTRY_PATTERNS.items():
            score = 0.0
            evidence_count = 0

            # Check domain patterns
            for pattern_domain in patterns["domains"]:
                if pattern_domain in domain:
                    score += 0.7
                    evidence_count += 1
                    break

            # Check keywords in company name
            if company_name:
                name_lower = company_name.lower()
                keyword_matches = sum(
                    1 for kw in patterns["keywords"] if kw in name_lower
                )
                if keyword_matches > 0:
                    score += min(0.5, keyword_matches * 0.2)
                    evidence_count += keyword_matches

            # Special case for .edu
            if industry == "education" and domain.endswith(".edu"):
                score = 0.95
                evidence_count += 1

            if evidence_count > 0:
                scores[industry] = min(0.95, score)

        return scores

    async def update_from_user_confirmation(
        self, account_id: str, updates: Dict[str, Any], user_id: str
    ) -> OrgProfile:
        """Update profile with user-confirmed data"""
        profile = await self.get_or_create_profile(account_id)

        # Update fields
        for key, value in updates.items():
            if hasattr(profile, key):
                setattr(profile, key, value)

        # Mark as confirmed
        profile.user_confirmed = {
            "confirmed_at": datetime.utcnow().isoformat(),
            "confirmed_by": user_id,
            "fields": list(updates.keys()),
        }

        # Boost confidence
        profile.profile_confidence = min(0.95, profile.profile_confidence + 0.3)

        # Clear cache
        if account_id in self._cache:
            del self._cache[account_id]

        await self.db.commit()
        await self.db.refresh(profile)
        return profile

    def get_weight_adjustments(self, profile: OrgProfile) -> Dict[str, float]:
        """Get weight adjustments based on industry"""
        if not profile.industry:
            return {}

        return INDUSTRY_WEIGHTS.get(profile.industry, {})

    def get_blocking_strategy(self, profile: OrgProfile) -> Dict[str, Any]:
        """Get blocking strategy based on context"""
        strategy = {"name_trigram": True, "domain": True, "phone": True}

        if profile.industry == "healthcare_provider":
            strategy["geo"] = True
            strategy["first_word"] = True  # "Banner", "Kaiser", etc.
        elif profile.industry == "manufacturing":
            strategy["phone_prefix"] = True
            strategy["domain_exact"] = True
        elif profile.hierarchy_complexity == "high":
            strategy["hierarchical"] = True

        return strategy

    def get_threshold_adjustments(self, profile: OrgProfile) -> Dict[str, float]:
        """Get threshold adjustments based on context"""
        adjustments = {}

        if profile.hierarchy_complexity == "high":
            # Be more conservative with auto-linking
            adjustments["auto_link"] = 0.97
            adjustments["suggest"] = 0.80
        elif profile.hierarchy_complexity == "low":
            # Can be more aggressive
            adjustments["auto_link"] = 0.93
            adjustments["suggest"] = 0.73

        if profile.sales_motion == "B2C":
            # Personal emails common, need higher name match
            adjustments["suggest"] = 0.78

        return adjustments
