# 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

"""Centralized service catalog for the connect wizard and auto-setup engine.

Consolidates scattered service metadata (display names, doc links, env vars,
test URLs, job class relevance) into one authoritative registry.
"""

from __future__ import annotations

from dataclasses import dataclass, field

from ._helpers import SERVICE_DISPLAY, SERVICE_DOCS


@dataclass
class ServiceEntry:
    """Metadata for a single connectable service."""

    key: str
    display_name: str
    category: str  # "llm" | "integrations" | "apis" | "selfhosted" | "security"
    env_vars: list[str]
    doc_url: str
    doc_hint: str
    job_classes: list[str] = field(default_factory=list)
    credential_type: str = "single_token"
    # "single_token" | "url_and_token" | "multi_field" | "oauth" | "local"
    setup_complexity: str = "paste_key"
    # "paste_key" | "url_and_key" | "multi_step" | "oauth_flow" | "local_install"
    test_url: str | None = None
    test_headers: dict[str, str] | None = None
    test_params: dict[str, str] | None = None


def _entry(
    key: str,
    category: str,
    env_vars: list[str],
    *,
    credential_type: str = "single_token",
    setup_complexity: str = "paste_key",
    job_classes: list[str] | None = None,
    test_url: str | None = None,
    test_headers: dict[str, str] | None = None,
    test_params: dict[str, str] | None = None,
) -> ServiceEntry:
    """Build a ServiceEntry pulling display_name/docs from _helpers.py."""
    display_name = SERVICE_DISPLAY.get(key, key)
    doc = SERVICE_DOCS.get(key, ("", ""))
    return ServiceEntry(
        key=key,
        display_name=display_name,
        category=category,
        env_vars=env_vars,
        doc_url=doc[0],
        doc_hint=doc[1],
        job_classes=job_classes or [],
        credential_type=credential_type,
        setup_complexity=setup_complexity,
        test_url=test_url,
        test_headers=test_headers,
        test_params=test_params,
    )


# ── Service Catalog ──────────────────────────────────────────────────

SERVICE_CATALOG: dict[str, ServiceEntry] = {}

_ENTRIES: list[ServiceEntry] = [
    # ── LLM providers ────────────────────────────────────────────────
    _entry(
        "anthropic",
        "llm",
        ["ANTHROPIC_API_KEY"],
        test_url="https://api.anthropic.com/v1/messages",
    ),
    _entry(
        "openai",
        "llm",
        ["OPENAI_API_KEY"],
        test_url="https://api.openai.com/v1/models",
        test_headers={"Authorization": "Bearer {token}"},
    ),
    _entry(
        "gemini",
        "llm",
        ["GEMINI_API_KEY"],
    ),
    _entry(
        "ollama",
        "llm",
        [],
        credential_type="local",
        setup_complexity="local_install",
    ),
    # ── Integrations ─────────────────────────────────────────────────
    _entry(
        "google",
        "integrations",
        ["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET"],
        credential_type="oauth",
        setup_complexity="oauth_flow",
    ),
    _entry(
        "calendar",
        "integrations",
        ["CALDAV_URL", "CALDAV_USERNAME", "CALDAV_PASSWORD"],
        credential_type="multi_field",
        setup_complexity="multi_step",
    ),
    _entry(
        "email",
        "integrations",
        ["EMAIL_ADDRESS", "EMAIL_PASSWORD", "EMAIL_IMAP_SERVER", "EMAIL_SMTP_SERVER"],
        credential_type="multi_field",
        setup_complexity="multi_step",
        job_classes=[
            "helper",
            "social_worker",
            "business_buddy",
            "nonprofit_director",
            "chef",
            "artist",
        ],
    ),
    _entry(
        "sms",
        "integrations",
        ["TWILIO_ACCOUNT_SID", "TWILIO_AUTH_TOKEN", "TWILIO_PHONE_NUMBER"],
        credential_type="multi_field",
        setup_complexity="multi_step",
    ),
    _entry(
        "browser",
        "integrations",
        [],
        credential_type="local",
        setup_complexity="local_install",
    ),
    _entry(
        "voice",
        "integrations",
        [],
        credential_type="local",
        setup_complexity="local_install",
    ),
    _entry(
        "websearch",
        "integrations",
        [],
        credential_type="local",
        setup_complexity="local_install",
        job_classes=["helper"],
    ),
    _entry(
        "healthcare",
        "integrations",
        [],
        credential_type="local",
        setup_complexity="multi_step",
        job_classes=["social_worker"],
    ),
    _entry(
        "github",
        "integrations",
        ["GITHUB_TOKEN"],
        test_url="https://api.github.com/user",
        test_headers={"Authorization": "Bearer {token}"},
    ),
    _entry(
        "slack",
        "integrations",
        ["SLACK_BOT_TOKEN", "SLACK_APP_TOKEN"],
        credential_type="multi_field",
        setup_complexity="multi_step",
    ),
    # ── API services ─────────────────────────────────────────────────
    _entry(
        "hubspot",
        "apis",
        ["HUBSPOT_ACCESS_TOKEN"],
        job_classes=["business_buddy", "nonprofit_director"],
        test_url="https://api.hubapi.com/crm/v3/objects/contacts",
        test_headers={"Authorization": "Bearer {token}"},
        test_params={"limit": "1"},
    ),
    _entry(
        "todoist",
        "apis",
        ["TODOIST_API_TOKEN"],
        job_classes=["business_buddy", "nonprofit_director", "social_worker", "artist"],
        test_url="https://api.todoist.com/rest/v2/projects",
        test_headers={"Authorization": "Bearer {token}"},
    ),
    _entry(
        "stripe",
        "apis",
        ["STRIPE_SECRET_KEY"],
        job_classes=["business_buddy", "nonprofit_director", "artist"],
        test_url="https://api.stripe.com/v1/balance",
        test_headers={"Authorization": "Bearer {token}"},
    ),
    _entry(
        "square",
        "apis",
        ["SQUARE_ACCESS_TOKEN"],
        job_classes=["chef", "artist"],
        test_url="https://connect.squareup.com/v2/locations",
        test_headers={"Authorization": "Bearer {token}"},
    ),
    _entry(
        "mailerlite",
        "apis",
        ["MAILERLITE_API_KEY"],
        job_classes=["business_buddy", "nonprofit_director"],
        test_url="https://connect.mailerlite.com/api/subscribers",
        test_headers={"Authorization": "Bearer {token}"},
        test_params={"limit": "1"},
    ),
    _entry(
        "shippo",
        "apis",
        ["SHIPPO_API_KEY"],
        test_url="https://api.goshippo.com/addresses/",
        test_headers={"ShippoToken": "shippo_test_{token}"},
    ),
    _entry(
        "calcom",
        "apis",
        ["CALCOM_API_KEY"],
        test_url="https://api.cal.com/v1/me",
        test_params={"apiKey": "{token}"},
    ),
    _entry(
        "brave_search",
        "apis",
        ["BRAVE_SEARCH_API_KEY"],
        job_classes=["helper"],
        test_url="https://api.search.brave.com/res/v1/web/search",
        test_headers={"X-Subscription-Token": "{token}"},
        test_params={"q": "test", "count": "1"},
    ),
    _entry(
        "spoonacular",
        "apis",
        ["SPOONACULAR_API_KEY"],
        job_classes=["chef"],
        test_url="https://api.spoonacular.com/recipes/complexSearch",
        test_params={"apiKey": "{token}", "number": "1"},
    ),
    _entry(
        "reddit",
        "apis",
        ["REDDIT_CLIENT_ID", "REDDIT_CLIENT_SECRET"],
        credential_type="multi_field",
        setup_complexity="multi_step",
    ),
    _entry(
        "etsy",
        "apis",
        ["ETSY_API_KEY", "ETSY_SHOP_ID"],
        credential_type="multi_field",
        setup_complexity="multi_step",
        job_classes=["artist"],
    ),
    _entry(
        "clockify",
        "apis",
        ["CLOCKIFY_API_KEY", "CLOCKIFY_WORKSPACE_ID"],
        credential_type="multi_field",
        setup_complexity="multi_step",
        job_classes=["business_buddy"],
        test_url="https://api.clockify.me/api/v1/user",
        test_headers={"X-Api-Key": "{token}"},
    ),
    _entry(
        "quickbooks",
        "apis",
        ["QUICKBOOKS_ACCESS_TOKEN", "QUICKBOOKS_REALM_ID"],
        credential_type="multi_field",
        setup_complexity="multi_step",
        job_classes=["business_buddy"],
    ),
    # ── Sprint 2-10 API services ────────────────────────────────────
    _entry(
        "google_trends",
        "apis",
        ["GOOGLE_TRENDS_API_KEY"],
        job_classes=["helper"],
    ),
    _entry(
        "news",
        "apis",
        ["GNEWS_API_KEY"],
        job_classes=["helper"],
    ),
    _entry(
        "cloudinary_img",
        "apis",
        ["CLOUDINARY_CLOUD_NAME", "CLOUDINARY_API_KEY"],
        credential_type="multi_field",
        setup_complexity="multi_step",
        job_classes=["artist"],
    ),
    _entry(
        "instagram",
        "apis",
        ["INSTAGRAM_ACCESS_TOKEN", "INSTAGRAM_BUSINESS_ID"],
        credential_type="multi_field",
        setup_complexity="multi_step",
        job_classes=["artist"],
    ),
    _entry(
        "civicrm",
        "apis",
        ["CIVICRM_URL", "CIVICRM_API_KEY"],
        credential_type="url_and_token",
        setup_complexity="url_and_key",
        job_classes=["nonprofit_director"],
    ),
    _entry(
        "globalgiving",
        "apis",
        ["GLOBALGIVING_API_KEY"],
        job_classes=["nonprofit_director"],
    ),
    _entry(
        "jitsi",
        "apis",
        ["JITSI_URL"],
    ),
    _entry(
        "kobo",
        "apis",
        ["KOBO_TOKEN"],
        job_classes=["social_worker"],
    ),
    _entry(
        "open_referral",
        "apis",
        ["OPEN_REFERRAL_URL"],
        job_classes=["social_worker"],
    ),
    # ── Self-Hosted ──────────────────────────────────────────────────
    _entry(
        "jellyfin",
        "selfhosted",
        ["JELLYFIN_URL", "JELLYFIN_TOKEN", "JELLYFIN_USER_ID"],
        credential_type="multi_field",
        setup_complexity="url_and_key",
    ),
    _entry(
        "gitea",
        "selfhosted",
        ["GITEA_URL", "GITEA_TOKEN"],
        credential_type="url_and_token",
        setup_complexity="url_and_key",
    ),
    _entry(
        "homeassistant",
        "selfhosted",
        ["HOMEASSISTANT_URL", "HOMEASSISTANT_TOKEN"],
        credential_type="url_and_token",
        setup_complexity="url_and_key",
    ),
    _entry(
        "joplin",
        "selfhosted",
        ["JOPLIN_TOKEN"],
        job_classes=["helper", "social_worker"],
    ),
    _entry(
        "pihole",
        "selfhosted",
        ["PIHOLE_URL", "PIHOLE_TOKEN"],
        credential_type="url_and_token",
        setup_complexity="url_and_key",
    ),
    _entry(
        "nextcloud",
        "selfhosted",
        ["NEXTCLOUD_URL", "NEXTCLOUD_USER", "NEXTCLOUD_TOKEN"],
        credential_type="multi_field",
        setup_complexity="url_and_key",
    ),
    _entry(
        "proton",
        "selfhosted",
        [],
        credential_type="local",
        setup_complexity="local_install",
    ),
    _entry(
        "email_server",
        "selfhosted",
        ["EMAIL_SERVER_DOMAIN"],
        credential_type="multi_field",
        setup_complexity="multi_step",
    ),
    _entry(
        "mealie",
        "selfhosted",
        ["MEALIE_URL", "MEALIE_TOKEN"],
        credential_type="url_and_token",
        setup_complexity="url_and_key",
        job_classes=["chef"],
    ),
    # ── Security ─────────────────────────────────────────────────────
    _entry(
        "vaultwarden",
        "security",
        ["VAULTWARDEN_URL", "VAULTWARDEN_TOKEN"],
        credential_type="url_and_token",
        setup_complexity="url_and_key",
    ),
    _entry(
        "encryption",
        "security",
        [],
        credential_type="local",
        setup_complexity="multi_step",
    ),
    _entry(
        "phi_detection",
        "security",
        [],
        credential_type="local",
        setup_complexity="multi_step",
    ),
    _entry(
        "rbac",
        "security",
        [],
        credential_type="local",
        setup_complexity="multi_step",
    ),
    _entry(
        "user_management",
        "security",
        [],
        credential_type="local",
        setup_complexity="multi_step",
    ),
]

for _e in _ENTRIES:
    SERVICE_CATALOG[_e.key] = _e


# ── Helper functions ─────────────────────────────────────────────────


def get_service(key: str) -> ServiceEntry | None:
    """Look up a single service by key."""
    return SERVICE_CATALOG.get(key)


def get_services_for_job_class(job_class: str) -> list[ServiceEntry]:
    """Return services relevant to a job class, sorted simplest-first."""
    complexity_order = {
        "paste_key": 0,
        "url_and_key": 1,
        "multi_step": 2,
        "oauth_flow": 3,
        "local_install": 4,
    }
    matches = [s for s in SERVICE_CATALOG.values() if job_class in s.job_classes]
    matches.sort(key=lambda s: complexity_order.get(s.setup_complexity, 99))
    return matches


def get_paste_key_services() -> list[ServiceEntry]:
    """Return services that only need a single API key pasted."""
    return [
        s for s in SERVICE_CATALOG.values() if s.credential_type == "single_token" and s.env_vars
    ]
