"""
scrylo/core/icp_scorer.py
--------------------------
ICP (Ideal Customer Profile) scoring for leads.

Pure keyword matching — zero downloads, zero RAM cost, runs in microseconds.
Sufficient for scoring 10-40 leads against a plain-English ICP description.

The ICP profile is set by the user in Settings:
  e.g. "B2B SaaS founder or CEO, 1-50 employees, English-speaking market"

Returns float 0.0-100.0, or None if no ICP profile is configured.
"""

from __future__ import annotations

import logging
import re
from typing import Optional

log = logging.getLogger("scrylo.icp")

_SENIORITY_WORDS = {
    "founder", "cofounder", "ceo", "chief", "executive",
    "owner", "president", "director", "managing",
    "cto", "coo", "cfo", "vp", "partner", "principal", "head",
}

_NEGATIVE_WORDS = {
    "journalist", "reporter", "editor", "writer",
    "student", "intern", "assistant", "coordinator",
}

_STOPS = {
    "and", "or", "the", "a", "an", "in", "at", "of", "for",
    "to", "is", "are", "with", "on", "by", "as", "from", "i",
    "my", "we", "our", "their", "its", "be", "do", "have",
}


def _tokens(text: str) -> set:
    return set(re.findall(r"[a-z0-9]+", text.lower())) - _STOPS


def _score_keyword(lead_text: str, icp_text: str) -> float:
    lead_tokens = _tokens(lead_text)
    icp_tokens  = _tokens(icp_text)

    if not icp_tokens:
        return 50.0

    overlap    = lead_tokens & icp_tokens
    base_score = min(60.0, len(overlap) / len(icp_tokens) * 100)

    lead_lower = lead_text.lower()
    icp_lower  = icp_text.lower()

    icp_wants_senior = any(w in icp_lower  for w in _SENIORITY_WORDS)
    lead_is_senior   = any(w in lead_lower for w in _SENIORITY_WORDS)
    lead_is_negative = any(w in lead_lower for w in _NEGATIVE_WORDS)

    if icp_wants_senior and lead_is_senior:
        base_score = min(100.0, base_score + 20)
    elif icp_wants_senior and not lead_is_senior:
        base_score = max(0.0, base_score - 15)

    if lead_is_negative:
        base_score = max(0.0, base_score - 25)

    return round(min(100.0, base_score), 1)


def _lead_to_text(
    role:     Optional[str],
    company:  Optional[str],
    location: Optional[str],
) -> str:
    return " ".join(p for p in [role, company, location] if p)


def score_lead(
    role:        Optional[str],
    company:     Optional[str],
    location:    Optional[str],
    icp_profile: str,
) -> Optional[float]:
    if not icp_profile or not icp_profile.strip():
        return None
    lead_text = _lead_to_text(role, company, location)
    if not lead_text:
        return 30.0
    return _score_keyword(lead_text, icp_profile)


def score_leads_batch(lead_ids: list, icp_profile: str) -> dict:
    if not lead_ids or not icp_profile or not icp_profile.strip():
        return {}

    from scrylo.db.session import db_session
    from scrylo.db.models import Lead

    results = {}
    with db_session() as db:
        leads = db.query(Lead).filter(Lead.id.in_(lead_ids)).all()
        for lead in leads:
            s = score_lead(lead.role, lead.company, lead.location, icp_profile)
            if s is not None:
                lead.icp_score = s
                results[lead.id] = s
        db.commit()

    log.info("ICP scored %d leads", len(results))
    return results
