# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Email: Georgescottfoley@proton.me
# Licensed under the MIT License - see LICENSE file for details

"""Tests for Sprint 1 skills: FoodData, NPI, SAMHSA, HRSA."""

from unittest.mock import MagicMock, patch

# Patch target for httpx — all skills use it via _api_utils
HTTPX_GET = "familiar.skills._api_utils.httpx.get"
HTTPX_POST = "familiar.skills._api_utils.httpx.post"
CACHE_GET = "familiar.core.api_cache.get_cached"
CACHE_SET = "familiar.core.api_cache.set_cached"


def _mock_response(data, status=200):
    resp = MagicMock()
    resp.status_code = status
    resp.json.return_value = data
    resp.content = b'{"ok": true}'
    return resp


# ── USDA FoodData Central ─────────────────────────────────────────────────


class TestFoodSearch:
    def test_empty_query(self):
        from familiar.skills.fooddata.skill import food_search

        result = food_search({"query": ""})
        assert "provide a search query" in result.lower()

    def test_success(self):
        from familiar.skills.fooddata.skill import food_search

        resp = _mock_response(
            {
                "totalHits": 2,
                "foods": [
                    {
                        "fdcId": 123,
                        "description": "Chicken breast, raw",
                        "dataType": "Foundation",
                        "brandOwner": "",
                    },
                    {
                        "fdcId": 456,
                        "description": "Chicken breast, grilled",
                        "dataType": "Branded",
                        "brandOwner": "Tyson",
                    },
                ],
            }
        )

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = food_search({"query": "chicken breast"})
        assert "Chicken breast, raw" in result
        assert "FDC ID: 123" in result
        assert "Tyson" in result

    def test_no_results(self):
        from familiar.skills.fooddata.skill import food_search

        resp = _mock_response({"totalHits": 0, "foods": []})

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = food_search({"query": "zzzznonexistent"})
        assert "No foods found" in result


class TestNutritionLookup:
    def test_no_id(self):
        from familiar.skills.fooddata.skill import nutrition_lookup

        result = nutrition_lookup({"fdc_id": ""})
        assert "provide an fdc id" in result.lower()

    def test_success(self):
        from familiar.skills.fooddata.skill import nutrition_lookup

        resp = _mock_response(
            {
                "description": "Chicken, breast, raw",
                "dataType": "Foundation",
                "servingSize": 100,
                "servingSizeUnit": "g",
                "foodNutrients": [
                    {"nutrient": {"name": "Energy", "unitName": "kcal"}, "amount": 120},
                    {"nutrient": {"name": "Protein", "unitName": "g"}, "amount": 22.5},
                ],
            }
        )

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = nutrition_lookup({"fdc_id": "123"})
        assert "Chicken, breast, raw" in result
        assert "Energy" in result
        assert "Protein" in result


class TestNutrientReport:
    def test_no_ids(self):
        from familiar.skills.fooddata.skill import nutrient_report

        result = nutrient_report({"fdc_ids": []})
        assert "Provide a list" in result

    def test_too_many(self):
        from familiar.skills.fooddata.skill import nutrient_report

        result = nutrient_report({"fdc_ids": [str(i) for i in range(25)]})
        assert "Maximum 20" in result


class TestFoodDataTools:
    def test_tools_registered(self):
        from familiar.skills.fooddata.skill import TOOLS

        names = [t["name"] for t in TOOLS]
        assert "food_search" in names
        assert "nutrition_lookup" in names
        assert "nutrient_report" in names

    def test_all_have_handlers(self):
        from familiar.skills.fooddata.skill import TOOLS

        for tool in TOOLS:
            assert callable(tool["handler"])


# ── NPI Registry ──────────────────────────────────────────────────────────


class TestProviderSearch:
    def test_no_criteria(self):
        from familiar.skills.npi.skill import provider_search

        result = provider_search({})
        assert "provide at least one" in result.lower()

    def test_success(self):
        from familiar.skills.npi.skill import provider_search

        resp = _mock_response(
            {
                "result_count": 1,
                "results": [
                    {
                        "number": "1234567890",
                        "enumeration_type": "NPI-1",
                        "basic": {
                            "first_name": "Jane",
                            "last_name": "Smith",
                            "credential": "MD",
                        },
                        "addresses": [
                            {
                                "address_purpose": "LOCATION",
                                "city": "Portland",
                                "state": "OR",
                                "postal_code": "97201",
                            }
                        ],
                        "taxonomies": [{"desc": "Family Medicine", "primary": True}],
                    }
                ],
            }
        )

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = provider_search({"last_name": "Smith", "state": "OR"})
        assert "Jane Smith, MD" in result
        assert "1234567890" in result
        assert "Portland" in result
        assert "Family Medicine" in result

    def test_no_results(self):
        from familiar.skills.npi.skill import provider_search

        resp = _mock_response({"result_count": 0, "results": []})

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = provider_search({"last_name": "Zzzznonexistent"})
        assert "No providers found" in result

    def test_organization_search(self):
        from familiar.skills.npi.skill import provider_search

        resp = _mock_response(
            {
                "result_count": 1,
                "results": [
                    {
                        "number": "9876543210",
                        "enumeration_type": "NPI-2",
                        "basic": {"organization_name": "Portland Community Health"},
                        "addresses": [],
                        "taxonomies": [],
                    }
                ],
            }
        )

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = provider_search({"organization_name": "Portland Community"})
        assert "Portland Community Health" in result


class TestNpiTools:
    def test_tools_registered(self):
        from familiar.skills.npi.skill import TOOLS

        names = [t["name"] for t in TOOLS]
        assert "provider_search" in names


# ── SAMHSA Treatment Locator ─────────────────────────────────────────────


class TestFindTreatment:
    def test_no_location(self):
        from familiar.skills.samhsa.skill import find_treatment

        result = find_treatment({})
        assert "provide a location" in result.lower()

    def test_success(self):
        from familiar.skills.samhsa.skill import find_treatment

        resp = _mock_response(
            {
                "totalResults": 2,
                "rows": [
                    {
                        "name1": "Recovery Center Portland",
                        "street1": "123 Main St",
                        "city": "Portland",
                        "state": "OR",
                        "zip": "97201",
                        "phone": "503-555-0100",
                        "sa": True,
                        "mh": True,
                        "dt": False,
                    },
                    {
                        "name1": "Mental Health Services Inc",
                        "city": "Portland",
                        "state": "OR",
                        "zip": "97205",
                        "phone": "503-555-0200",
                        "sa": False,
                        "mh": True,
                        "dt": False,
                    },
                ],
            }
        )

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = find_treatment({"city": "Portland", "state": "OR"})
        assert "Recovery Center Portland" in result
        assert "Mental Health Services" in result
        assert "1-800-662-4357" in result

    def test_api_failure_shows_fallback(self):
        from familiar.skills.samhsa.skill import find_treatment

        with (
            patch(HTTPX_GET, side_effect=Exception("connection refused")),
            patch(CACHE_GET, return_value=None),
        ):
            result = find_treatment({"zip_code": "97201"})
        assert "1-800-662-4357" in result
        assert "findtreatment.gov" in result


class TestSamhsaTools:
    def test_tools_registered(self):
        from familiar.skills.samhsa.skill import TOOLS

        names = [t["name"] for t in TOOLS]
        assert "find_treatment" in names


# ── HRSA Health Center Finder ─────────────────────────────────────────────


class TestFindHealthCenter:
    def test_no_location(self):
        from familiar.skills.hrsa.skill import find_health_center

        result = find_health_center({})
        assert "provide a location" in result.lower()

    def test_api_failure_shows_fallback(self):
        from familiar.skills.hrsa.skill import find_health_center

        with (
            patch(HTTPX_GET, side_effect=Exception("timeout")),
            patch(CACHE_GET, return_value=None),
        ):
            result = find_health_center({"zip_code": "97201"})
        assert "findahealthcenter.hrsa.gov" in result
        assert "sliding scale" in result.lower()

    def test_success(self):
        from familiar.skills.hrsa.skill import find_health_center

        resp = _mock_response(
            {
                "results": [
                    {
                        "name": "Multnomah County Health Center",
                        "address": "426 SW Stark St",
                        "city": "Portland",
                        "state": "OR",
                        "zip": "97204",
                        "phone": "503-555-0300",
                        "services": ["Primary Care", "Dental", "Mental Health"],
                    },
                ]
            }
        )

        with (
            patch(HTTPX_GET, return_value=resp),
            patch(CACHE_GET, return_value=None),
            patch(CACHE_SET),
        ):
            result = find_health_center({"city": "Portland", "state": "OR"})
        assert "Multnomah County Health Center" in result
        assert "ability to pay" in result.lower()


class TestHrsaTools:
    def test_tools_registered(self):
        from familiar.skills.hrsa.skill import TOOLS

        names = [t["name"] for t in TOOLS]
        assert "find_health_center" in names
