"""Tool 1: setup_profile — Analyze your LinkedIn profile and generate a voice signature.

This is the #1 killer feature. Voice matching was the strongest positive
reaction in 7 of 12 customer discovery interviews. This is where users
think "OK, this AI actually gets me."

Supports two modes:

**Direct mode** (Unipile credentials in config):
  Call 1: setup_profile(llm_api_key="...") → auth link → user connects LinkedIn
  Call 2: setup_profile() → polls for account → profile fetch → voice analysis

**Backend mode** (backend_url + backend_jwt in config):
  Call 1: setup_profile(llm_api_key="...", backend_url="...", backend_jwt="...")
          → saves config → connects LinkedIn via backend proxy → profile + voice

If the account is already connected (re-run), skips straight to profile fetch.
"""

from __future__ import annotations

import logging

from ..ai.voice_analyzer import analyze_voice
from ..config import (
    get_backend_config,
    get_unipile_config,
    is_backend_mode,
    load_config,
    save_config,
    set_backend_config,
)
from ..db.queries import get_setting, save_setting
from ..formatter import format_voice_signature
from ..linkedin import (
    UnipileAuthError,
    UnipileError,
    get_account_id,
    get_linkedin_client,
)

logger = logging.getLogger(__name__)


async def run_setup_profile(
    llm_api_key: str = "",
    llm_provider: str = "",
    backend_url: str = "",
    backend_jwt: str = "",
) -> str:
    """Set up the user's profile by analyzing their LinkedIn presence.

    Args:
        llm_api_key: API key for the LLM provider.
        llm_provider: Which LLM to use ("gemini", "claude", "openai").
        backend_url: HeyLead Backend API URL (enables backend mode).
        backend_jwt: JWT from Google OAuth (required for backend mode).

    Returns:
        Formatted string showing the voice analysis results or next-step instructions.
    """

    # ── Step 0: Handle LLM API key ──
    cfg = load_config()

    if llm_api_key:
        provider = llm_provider or "gemini"
        cfg.setdefault("api_keys", {})[provider] = llm_api_key
        save_config(cfg)

    has_llm_key = any(v for v in cfg.get("api_keys", {}).values() if v)
    if not has_llm_key and not llm_api_key:
        return (
            "❌ No LLM API key configured.\n\n"
            "Please provide an API key. You can:\n"
            "1. Pass it directly: setup_profile(llm_api_key='YOUR_KEY', llm_provider='gemini')\n"
            "2. Or add it to ~/.heylead/config.json\n\n"
            "Get a free Gemini key at: https://aistudio.google.com/apikey"
        )

    # ── Step 0b: Handle backend config ──
    if backend_url or backend_jwt:
        set_backend_config(
            backend_url or get_backend_config()[0],
            backend_jwt or get_backend_config()[1],
        )

    # ── Route to appropriate mode ──
    if is_backend_mode():
        return await _setup_backend_mode()
    else:
        return await _setup_direct_mode()


async def _setup_backend_mode() -> str:
    """Setup flow via HeyLead Backend API proxy."""
    client = get_linkedin_client()
    try:
        stored_account_id = get_account_id()

        if stored_account_id:
            connected, status_msg = await client.verify_account(stored_account_id)
            if connected:
                return await _fetch_and_analyze(client, stored_account_id)
            else:
                logger.info(f"Stored account no longer connected: {status_msg}")
                save_setting("unipile_account_id", None)

        # Check if we're in "waiting for OAuth" state
        auth_link_pending = get_setting("auth_link_pending", False)

        if auth_link_pending:
            known_ids = set(get_setting("known_account_ids_before_auth", []))
            account_id, poll_msg = await client.poll_for_new_account(known_ids)

            if account_id:
                save_setting("unipile_account_id", account_id)
                save_setting("auth_link_pending", False)
                save_setting("known_account_ids_before_auth", [])
                return await _fetch_and_analyze(client, account_id)
            else:
                return (
                    f"⏳ {poll_msg}\n\n"
                    "Please make sure you:\n"
                    "1. Opened the auth link in your browser\n"
                    "2. Completed the LinkedIn login\n"
                    "3. Saw a success confirmation\n\n"
                    "Then run setup_profile() again to retry."
                )

        # Snapshot existing accounts, then create auth link via backend
        known_ids = await client.get_existing_account_ids()

        try:
            auth_url = await client.create_hosted_auth_link()
        except UnipileError as e:
            return f"❌ Failed to create LinkedIn auth link: {e}"

        save_setting("auth_link_pending", True)
        save_setting("known_account_ids_before_auth", list(known_ids))

        return (
            "🔗 Almost there! Open this link in your browser to connect LinkedIn:\n\n"
            f"  {auth_url}\n\n"
            "Steps:\n"
            "1. Click the link above (or copy-paste into your browser)\n"
            "2. Log in to LinkedIn when prompted\n"
            "3. Authorize the connection\n"
            "4. Come back here and run setup_profile() again\n\n"
            "⏱️ The link expires in 24 hours.\n"
            "🔒 Your credentials are handled securely by the HeyLead backend."
        )

    except UnipileError as e:
        return f"❌ Backend error: {e}"
    except Exception as e:
        logger.error(f"setup_profile (backend mode) failed: {e}", exc_info=True)
        return f"❌ Setup failed: {e}\n\nCheck ~/.heylead/logs/heylead.log for details."
    finally:
        await client.close()


async def _setup_direct_mode() -> str:
    """Setup flow with direct Unipile credentials (original behavior)."""
    from ..config import get_unipile_config
    from ..linkedin.unipile import UnipileClient

    api_url, api_key = get_unipile_config()

    if not api_url or not api_key:
        return (
            "🔗 To set up your profile, I need connection credentials.\n\n"
            "Option 1 — Backend mode (recommended for new users):\n"
            "  setup_profile(backend_url='https://YOUR_BACKEND', backend_jwt='YOUR_TOKEN')\n\n"
            "Option 2 — Direct Unipile mode (for self-hosting):\n"
            "  Add to ~/.heylead/config.json:\n"
            '    "unipile_api_url": "https://apiXX.unipile.com:XXXXX",\n'
            '    "unipile_api_key": "YOUR_UNIPILE_API_KEY"\n\n'
            "Then run setup_profile again."
        )

    client = UnipileClient(api_url, api_key)
    try:
        stored_account_id = get_account_id()

        if stored_account_id:
            connected, status_msg = await client.verify_account(stored_account_id)
            if connected:
                return await _fetch_and_analyze(client, stored_account_id)
            else:
                logger.info(f"Stored account no longer connected: {status_msg}")
                save_setting("unipile_account_id", None)

        # Check if we're in "waiting for OAuth" state
        auth_link_pending = get_setting("auth_link_pending", False)

        if auth_link_pending:
            known_ids = set(get_setting("known_account_ids_before_auth", []))
            account_id, poll_msg = await client.poll_for_new_account(known_ids)

            if account_id:
                save_setting("unipile_account_id", account_id)
                save_setting("auth_link_pending", False)
                save_setting("known_account_ids_before_auth", [])
                return await _fetch_and_analyze(client, account_id)
            else:
                return (
                    f"⏳ {poll_msg}\n\n"
                    "Please make sure you:\n"
                    "1. Opened the auth link in your browser\n"
                    "2. Completed the LinkedIn login\n"
                    "3. Saw a success confirmation\n\n"
                    "Then run setup_profile() again to retry."
                )

        # Snapshot existing accounts, then create auth link
        known_ids = await client.get_existing_account_ids()

        try:
            auth_url = await client.create_hosted_auth_link()
        except UnipileError as e:
            return f"❌ Failed to create LinkedIn auth link: {e}"

        save_setting("auth_link_pending", True)
        save_setting("known_account_ids_before_auth", list(known_ids))

        return (
            "🔗 Almost there! Open this link in your browser to connect LinkedIn:\n\n"
            f"  {auth_url}\n\n"
            "Steps:\n"
            "1. Click the link above (or copy-paste into your browser)\n"
            "2. Log in to LinkedIn when prompted\n"
            "3. Authorize the connection\n"
            "4. Come back here and run setup_profile() again\n\n"
            "⏱️ The link expires in 24 hours.\n"
            "🔒 Your credentials are handled by Unipile — nothing stored locally."
        )

    except UnipileError as e:
        return f"❌ Unipile error: {e}"
    except Exception as e:
        logger.error(f"setup_profile failed: {e}", exc_info=True)
        return f"❌ Setup failed: {e}\n\nCheck ~/.heylead/logs/heylead.log for details."
    finally:
        await client.close()


async def _fetch_and_analyze(client, account_id: str) -> str:
    """Fetch profile, analyze voice, store results, return formatted output.

    Works with both UnipileClient and BackendClient.
    """

    # ── Fetch LinkedIn profile ──
    try:
        profile = await client.get_own_profile(account_id)
    except UnipileAuthError:
        save_setting("unipile_account_id", None)
        return (
            "❌ LinkedIn account disconnected.\n\n"
            "Run setup_profile() again to reconnect."
        )
    except Exception as e:
        logger.error(f"Failed to fetch LinkedIn profile: {e}")
        return (
            f"❌ Failed to fetch your LinkedIn profile: {e}\n\n"
            "This might be a temporary issue. Try again in a minute."
        )

    if not profile.get("name"):
        return (
            "❌ Could not read your LinkedIn profile.\n"
            "The connection might need to be refreshed. Run setup_profile() again."
        )

    # ── Fetch posts ──
    try:
        provider_id = profile.get("provider_id", "")
        posts = await client.get_posts(account_id, provider_id=provider_id)
        profile["posts"] = posts
    except Exception as e:
        logger.warning(f"Failed to fetch posts (non-fatal): {e}")
        profile["posts"] = []

    # ── Analyze voice with LLM ──
    try:
        analysis = await analyze_voice(profile)
    except Exception as e:
        logger.error(f"Voice analysis failed: {e}")
        return (
            f"❌ Voice analysis failed: {e}\n\n"
            "Check your LLM API key in ~/.heylead/config.json\n"
            "Get a free Gemini key at: https://aistudio.google.com/apikey"
        )

    voice = analysis.get("voice", {})
    expertise = analysis.get("expertise", {})

    # ── Store in database ──
    save_setting("profile", profile)
    save_setting("voice_signature", voice)
    save_setting("expertise_map", expertise)
    save_setting("setup_complete", True)

    # ── Format and return ──
    output = format_voice_signature(voice, expertise)

    header = (
        f"👤 {profile['name']}"
        + (f" — {profile['title']}" if profile.get("title") else "")
        + (f" at {profile['company']}" if profile.get("company") else "")
        + "\n"
        + (f"📍 {profile['location']}\n" if profile.get("location") else "")
        + (f"🔗 {profile['profile_url']}\n" if profile.get("profile_url") else "")
        + f"📝 {len(profile.get('posts', []))} recent posts analyzed\n"
        + "\n"
    )

    return header + output
