"""Collector: profile_view_collector — Detect who viewed your LinkedIn profile.

Polls get_profile_viewers() (requires LinkedIn Premium or Sales Navigator),
cross-references viewers against campaign contacts, and saves as
SIGNAL_PROFILE_VIEW signals.
"""

from __future__ import annotations

import json
import logging
import time
from typing import Any

from ..constants import (
    SIGNAL_PROFILE_VIEW,
    SIGNAL_TTL_PROFILE_VIEW,
)
from ..db.queries import get_setting
from ..db.signal_queries import (
    get_contact_by_linkedin_id,
    save_signal,
    signal_exists,
    upsert_signal_account,
)

logger = logging.getLogger(__name__)


async def collect_profile_views() -> str:
    """Collect profile view signals from LinkedIn.

    Flow:
    1. Call get_profile_viewers() to get recent viewers
    2. For each viewer, extract name/title/company/url
    3. Try to resolve linkedin_id from URL
    4. Cross-reference against campaign contacts
    5. Save as SIGNAL_PROFILE_VIEW signals
    6. Update signal_accounts aggregation

    Returns:
        Summary string of results.
    """
    from ..linkedin import get_account_id, get_linkedin_client

    account_id = get_account_id()
    if not account_id:
        return "No LinkedIn account connected — skipping profile view collection."

    client = get_linkedin_client()
    total_signals = 0
    errors = 0

    try:
        viewers = await client.get_profile_viewers(account_id)

        if not viewers:
            return "No profile viewers found (requires LinkedIn Premium)."

        now = int(time.time())

        for viewer in viewers:
            viewer_name = viewer.get("name", "")
            viewer_title = viewer.get("title", "")
            viewer_company = viewer.get("company", "")
            viewer_url = viewer.get("url", "")

            if not viewer_name:
                continue

            # Try to extract linkedin_id from URL or other fields
            linkedin_id = _extract_linkedin_id(viewer_url, viewer)

            # Deduplicate: check if we already have a profile_view signal
            # for this person within the TTL window
            if linkedin_id:
                if signal_exists(
                    SIGNAL_PROFILE_VIEW,
                    linkedin_id=linkedin_id,
                    lookback_seconds=SIGNAL_TTL_PROFILE_VIEW,
                ):
                    continue
            elif viewer_name:
                # Fallback dedup by name (less reliable)
                if signal_exists(
                    SIGNAL_PROFILE_VIEW,
                    linkedin_id=viewer_name,  # Use name as pseudo-ID
                    lookback_seconds=SIGNAL_TTL_PROFILE_VIEW,
                ):
                    continue

            # Cross-reference against campaign contacts
            contact = None
            campaign_id = None
            prospect_id = None

            if linkedin_id:
                contact = get_contact_by_linkedin_id(linkedin_id)
                if contact:
                    campaign_id = contact.get("campaign_id")
                    prospect_id = contact.get("id")

            try:
                expires_at = now + SIGNAL_TTL_PROFILE_VIEW

                save_signal(
                    signal_type=SIGNAL_PROFILE_VIEW,
                    source="profile_viewers",
                    prospect_id=prospect_id,
                    prospect_name=viewer_name,
                    prospect_title=viewer_title,
                    linkedin_id=linkedin_id or viewer_name,
                    campaign_id=campaign_id,
                    content=f"Viewed your LinkedIn profile",
                    metadata_json=json.dumps({
                        "viewer_company": viewer_company,
                        "viewer_url": viewer_url,
                        "is_campaign_contact": contact is not None,
                        "relation": viewer.get("relation", ""),
                    }),
                    expires_at=expires_at,
                )
                total_signals += 1

                # Update signal account aggregation
                if linkedin_id:
                    upsert_signal_account(
                        linkedin_id=linkedin_id,
                        prospect_name=viewer_name,
                        company=viewer_company,
                    )

                if contact:
                    logger.info(
                        "Profile viewer cross-reference: %s is campaign contact (campaign=%s)",
                        viewer_name, campaign_id[:8] if campaign_id else "?",
                    )

            except Exception as e:
                logger.warning("Error saving profile view signal for %s: %s", viewer_name, e)
                errors += 1

    except Exception as e:
        logger.warning("Profile view collection failed: %s", e)
        return f"Profile view collection failed: {e}"
    finally:
        await client.close()

    summary = f"Profile view collection: {total_signals} new signals from {len(viewers)} viewers"
    if errors:
        summary += f", {errors} errors"
    logger.info(summary)
    return summary


def _extract_linkedin_id(url: str, viewer: dict[str, Any]) -> str:
    """Try to extract a LinkedIn provider_id or public_id from a viewer.

    Args:
        url: The viewer's LinkedIn profile URL.
        viewer: Full viewer dict from get_profile_viewers().

    Returns:
        LinkedIn ID string, or empty string if not extractable.
    """
    # Check for direct provider_id field
    provider_id = viewer.get("provider_id", "") or viewer.get("linkedin_id", "")
    if provider_id:
        return str(provider_id)

    # Try to extract from URL
    if not url:
        return ""

    # URLs like https://www.linkedin.com/in/johndoe or /in/johndoe/
    import re

    match = re.search(r"linkedin\.com/in/([^/?#]+)", url)
    if match:
        return match.group(1).strip("/")

    # URLs with member ID: /profile/view?id=12345
    match = re.search(r"[?&]id=(\d+)", url)
    if match:
        return match.group(1)

    return ""
