"""Contacts skill — lightweight CRM with interaction logging and deal pipeline."""

from datetime import datetime, timezone

from fliiq.runtime.config import resolve_fliiq_dir
from fliiq.runtime.ulid import generate_id
from fliiq.runtime.yaml_store import YamlStore

_STAGES_ORDER = ["lead", "qualified", "proposal", "negotiation", "closed_won", "closed_lost"]


def _store() -> YamlStore:
    return YamlStore(resolve_fliiq_dir() / "contacts.yaml", "contacts")


def _now_iso() -> str:
    return datetime.now(timezone.utc).isoformat()


def _today() -> str:
    return datetime.now(timezone.utc).strftime("%Y-%m-%d")


async def handler(params: dict) -> dict:
    action = params["action"]

    if action == "add":
        return _add(params)
    if action == "search":
        return _search(params)
    if action == "update":
        return _update(params)
    if action == "log_interaction":
        return _log_interaction(params)
    if action == "pipeline":
        return _pipeline(params)

    raise ValueError(f"Unknown action: {action}")


def _add(params: dict) -> dict:
    name = params.get("name")
    if not name:
        raise ValueError("name is required for add action")

    store = _store()
    items = store.load()

    # Dedup warning on email
    email = params.get("email")
    if email:
        existing = [c for c in items if c.get("email", "").lower() == email.lower()]
        if existing:
            return {
                "success": False,
                "message": f"A contact with email {email} already exists: {existing[0]['name']} ({existing[0]['id']})",
            }

    now = _now_iso()
    contact = {
        "id": generate_id("c"),
        "name": name,
        "email": email,
        "phone": params.get("phone"),
        "company": params.get("company"),
        "role": params.get("role"),
        "tags": params.get("tags", []),
        "notes": params.get("notes", ""),
        "deal": None,
        "interactions": [],
        "created": now,
        "updated": now,
    }
    items.append(contact)
    store.save(items)
    return {"success": True, "message": f"Added contact: {name}", "contact": contact}


def _search(params: dict) -> dict:
    query = params.get("query", "").lower()
    if not query:
        raise ValueError("query is required for search action")

    store = _store()
    items = store.load()

    results = []
    for c in items:
        searchable = " ".join([
            c.get("name", ""),
            c.get("email", "") or "",
            c.get("company", "") or "",
            c.get("role", "") or "",
            c.get("notes", "") or "",
            " ".join(c.get("tags", [])),
        ]).lower()

        if query in searchable:
            # Score: name match is highest priority
            score = 0
            if query in (c.get("name", "") or "").lower():
                score = 2
            elif query in (c.get("email", "") or "").lower():
                score = 1
            results.append((score, c))

    results.sort(key=lambda x: -x[0])
    contacts = [r[1] for r in results]

    return {"success": True, "count": len(contacts), "contacts": contacts}


def _find_contact(items: list[dict], contact_id: str) -> tuple[int, dict]:
    for i, c in enumerate(items):
        if c["id"] == contact_id:
            return i, c
    raise ValueError(f"Contact not found: {contact_id}")


def _update(params: dict) -> dict:
    contact_id = params.get("contact_id")
    if not contact_id:
        raise ValueError("contact_id is required for update action")

    store = _store()
    items = store.load()
    idx, contact = _find_contact(items, contact_id)

    # Update basic fields
    updatable = ("name", "email", "phone", "company", "role", "tags", "notes")
    for key in updatable:
        if key in params:
            contact[key] = params[key]

    # Update deal fields
    deal_stage = params.get("deal_stage")
    deal_value = params.get("deal_value")
    if deal_stage or deal_value is not None:
        if contact.get("deal") is None:
            contact["deal"] = {"stage": "lead", "value": 0, "currency": "USD"}
        if deal_stage:
            contact["deal"]["stage"] = deal_stage
        if deal_value is not None:
            contact["deal"]["value"] = deal_value

    contact["updated"] = _now_iso()
    items[idx] = contact
    store.save(items)
    return {"success": True, "message": f"Updated contact: {contact['name']}", "contact": contact}


def _log_interaction(params: dict) -> dict:
    contact_id = params.get("contact_id")
    if not contact_id:
        raise ValueError("contact_id is required for log_interaction action")

    interaction_type = params.get("interaction_type")
    if not interaction_type:
        raise ValueError("interaction_type is required for log_interaction action")

    summary = params.get("summary", "")

    store = _store()
    items = store.load()
    idx, contact = _find_contact(items, contact_id)

    interaction = {
        "date": _today(),
        "type": interaction_type,
        "summary": summary,
    }
    if contact.get("interactions") is None:
        contact["interactions"] = []
    contact["interactions"].append(interaction)
    contact["updated"] = _now_iso()

    items[idx] = contact
    store.save(items)
    return {
        "success": True,
        "message": f"Logged {interaction_type} with {contact['name']}",
        "interaction": interaction,
    }


def _pipeline(params: dict) -> dict:
    store = _store()
    items = store.load()
    filter_stage = params.get("filter_stage")

    stages: dict[str, list] = {s: [] for s in _STAGES_ORDER}

    for c in items:
        deal = c.get("deal")
        if not deal:
            continue
        stage = deal.get("stage", "lead")
        if filter_stage and stage != filter_stage:
            continue
        if stage in stages:
            stages[stage].append({
                "name": c["name"],
                "company": c.get("company"),
                "value": deal.get("value", 0),
                "id": c["id"],
            })

    summary = {}
    total_value = 0
    for stage, deals in stages.items():
        if not deals and not filter_stage:
            continue
        stage_value = sum(d["value"] for d in deals)
        total_value += stage_value
        summary[stage] = {"count": len(deals), "value": stage_value, "deals": deals}

    return {"success": True, "pipeline": summary, "total_value": total_value}
