"""Tests for contacts skill handler."""

import os

import pytest

from fliiq.runtime.package_data import bundled_skills_dir
from fliiq.runtime.skills.base import SkillBase

SKILLS_DIR = str(bundled_skills_dir())


def _load_skill(name: str) -> SkillBase:
    return SkillBase(os.path.join(SKILLS_DIR, name))


def test_contacts_skill_loads():
    skill = _load_skill("contacts")
    assert skill.name == "contacts"
    schema = skill.schema()
    assert "action" in schema["parameters"]["properties"]
    assert "add" in schema["parameters"]["properties"]["action"]["enum"]


def _setup_fliiq(tmp_path, monkeypatch):
    monkeypatch.chdir(tmp_path)
    fliiq_dir = tmp_path / ".fliiq"
    fliiq_dir.mkdir()
    return fliiq_dir


async def test_add_contact(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    result = await handler({
        "action": "add",
        "name": "Sarah Chen",
        "email": "sarah@acme.com",
        "company": "Acme Corp",
        "role": "VP Engineering",
        "tags": ["client"],
    })
    assert result["success"] is True
    assert result["contact"]["name"] == "Sarah Chen"
    assert result["contact"]["id"].startswith("c_")


async def test_add_contact_requires_name(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    with pytest.raises(ValueError, match="name is required"):
        await handler({"action": "add"})


async def test_add_contact_dedup_email(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    await handler({"action": "add", "name": "Sarah Chen", "email": "sarah@acme.com"})
    result = await handler({"action": "add", "name": "Sarah Duplicate", "email": "sarah@acme.com"})
    assert result["success"] is False
    assert "already exists" in result["message"]


async def test_search_by_name(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    await handler({"action": "add", "name": "Sarah Chen", "company": "Acme"})
    await handler({"action": "add", "name": "John Doe", "company": "Beta Inc"})

    result = await handler({"action": "search", "query": "Sarah"})
    assert result["count"] == 1
    assert result["contacts"][0]["name"] == "Sarah Chen"


async def test_search_by_company(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    await handler({"action": "add", "name": "Sarah Chen", "company": "Acme"})
    await handler({"action": "add", "name": "John Doe", "company": "Beta Inc"})

    result = await handler({"action": "search", "query": "acme"})
    assert result["count"] == 1
    assert result["contacts"][0]["name"] == "Sarah Chen"


async def test_search_by_tag(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    await handler({"action": "add", "name": "Sarah Chen", "tags": ["investor"]})
    await handler({"action": "add", "name": "John Doe", "tags": ["client"]})

    result = await handler({"action": "search", "query": "investor"})
    assert result["count"] == 1
    assert result["contacts"][0]["name"] == "Sarah Chen"


async def test_search_requires_query(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    with pytest.raises(ValueError, match="query is required"):
        await handler({"action": "search"})


async def test_update_contact(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    r = await handler({"action": "add", "name": "Sarah Chen"})
    contact_id = r["contact"]["id"]

    result = await handler({
        "action": "update",
        "contact_id": contact_id,
        "phone": "+1-555-0123",
        "company": "New Corp",
    })
    assert result["success"] is True
    assert result["contact"]["phone"] == "+1-555-0123"
    assert result["contact"]["company"] == "New Corp"


async def test_update_deal_fields(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    r = await handler({"action": "add", "name": "Sarah Chen"})
    contact_id = r["contact"]["id"]

    result = await handler({
        "action": "update",
        "contact_id": contact_id,
        "deal_stage": "proposal",
        "deal_value": 25000,
    })
    assert result["contact"]["deal"]["stage"] == "proposal"
    assert result["contact"]["deal"]["value"] == 25000


async def test_update_contact_not_found(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    with pytest.raises(ValueError, match="Contact not found"):
        await handler({"action": "update", "contact_id": "c_nonexistent", "name": "X"})


async def test_log_interaction(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    r = await handler({"action": "add", "name": "Sarah Chen"})
    contact_id = r["contact"]["id"]

    result = await handler({
        "action": "log_interaction",
        "contact_id": contact_id,
        "interaction_type": "meeting",
        "summary": "Demo call, positive response",
    })
    assert result["success"] is True
    assert result["interaction"]["type"] == "meeting"


async def test_log_interaction_appends(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    r = await handler({"action": "add", "name": "Sarah Chen"})
    cid = r["contact"]["id"]

    await handler({"action": "log_interaction", "contact_id": cid, "interaction_type": "meeting", "summary": "First"})
    await handler({"action": "log_interaction", "contact_id": cid, "interaction_type": "email", "summary": "Second"})

    # Search and check interactions
    result = await handler({"action": "search", "query": "Sarah"})
    contact = result["contacts"][0]
    assert len(contact["interactions"]) == 2
    assert contact["interactions"][0]["summary"] == "First"
    assert contact["interactions"][1]["summary"] == "Second"


async def test_pipeline_view(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    # Add contacts with deals
    r1 = await handler({"action": "add", "name": "Alice"})
    await handler({"action": "update", "contact_id": r1["contact"]["id"], "deal_stage": "proposal", "deal_value": 10000})

    r2 = await handler({"action": "add", "name": "Bob"})
    await handler({"action": "update", "contact_id": r2["contact"]["id"], "deal_stage": "proposal", "deal_value": 20000})

    r3 = await handler({"action": "add", "name": "Charlie"})
    await handler({"action": "update", "contact_id": r3["contact"]["id"], "deal_stage": "lead", "deal_value": 5000})

    # No deal
    await handler({"action": "add", "name": "No Deal Dan"})

    result = await handler({"action": "pipeline"})
    assert result["success"] is True
    assert result["pipeline"]["proposal"]["count"] == 2
    assert result["pipeline"]["proposal"]["value"] == 30000
    assert result["pipeline"]["lead"]["count"] == 1
    assert result["total_value"] == 35000


async def test_pipeline_filter_stage(tmp_path, monkeypatch):
    _setup_fliiq(tmp_path, monkeypatch)
    from fliiq.data.skills.core.contacts.main import handler

    r1 = await handler({"action": "add", "name": "Alice"})
    await handler({"action": "update", "contact_id": r1["contact"]["id"], "deal_stage": "proposal", "deal_value": 10000})
    r2 = await handler({"action": "add", "name": "Bob"})
    await handler({"action": "update", "contact_id": r2["contact"]["id"], "deal_stage": "lead", "deal_value": 5000})

    result = await handler({"action": "pipeline", "filter_stage": "proposal"})
    assert "proposal" in result["pipeline"]
    # Lead should be empty or missing since we filtered
    assert result["pipeline"].get("lead", {}).get("count", 0) == 0
