"""Tool 1b: switch_account — List connected LinkedIn accounts and switch between them.

Fetches all LinkedIn accounts from Unipile, shows them with profile info
(name, headline, LinkedIn URL), and lets the user pick which one to use.
Then re-runs profile fetch + voice analysis for the selected account.
"""

from __future__ import annotations

import logging

from ..ai.voice_analyzer import analyze_voice
from ..config import is_backend_mode
from ..db.queries import get_setting, save_setting
from ..formatter import format_voice_signature
from ..linkedin import get_account_id, get_linkedin_client

logger = logging.getLogger(__name__)


async def run_switch_account() -> str:
    """List all LinkedIn accounts and let the user pick one."""
    if not is_backend_mode():
        from ..config import get_unipile_config

        api_url, api_key = get_unipile_config()
        if not api_url or not api_key:
            return "❌ Not connected. Run setup_profile first."

    client = get_linkedin_client()
    try:
        accounts = await client.list_accounts()

        # Filter to LinkedIn accounts only
        linkedin_accounts = []
        for acc in accounts:
            provider = (
                acc.get("provider")
                or acc.get("provider_type")
                or acc.get("type")
                or ""
            )
            if "LINKEDIN" not in str(provider).upper():
                continue
            acc_id = (
                acc.get("id")
                or acc.get("account_id")
                or acc.get("accountId")
                or acc.get("uuid")
            )
            if not acc_id:
                continue
            linkedin_accounts.append(
                {
                    "id": str(acc_id),
                    "name": acc.get("name") or "",
                    "status": acc.get("status") or acc.get("state") or "unknown",
                    "created_at": acc.get("created_at") or acc.get("createdAt") or "",
                }
            )

        if not linkedin_accounts:
            return (
                "❌ No LinkedIn accounts found.\n\n"
                "Run setup_profile() to connect your LinkedIn account."
            )

        current_id = get_account_id()

        # Fetch profile info for each account to show LinkedIn URLs
        enriched = []
        for acc in linkedin_accounts:
            profile_info = ""
            try:
                profile = await client.get_own_profile(acc["id"])
                name = profile.get("name", "")
                headline = profile.get("headline", "")
                url = profile.get("profile_url", "")
                parts = []
                if name:
                    parts.append(name)
                if headline:
                    parts.append(headline)
                if url:
                    parts.append(url)
                profile_info = " — ".join(parts)
            except Exception:
                profile_info = f"(couldn't fetch profile for {acc['id']})"

            is_current = " ← current" if acc["id"] == current_id else ""
            enriched.append(
                {
                    "id": acc["id"],
                    "display": profile_info or acc["name"] or acc["id"],
                    "is_current": bool(is_current),
                    "marker": is_current,
                }
            )

        # Format the list
        lines = ["**Connected LinkedIn accounts:**\n"]
        for i, acc in enumerate(enriched, 1):
            lines.append(f"{i}. `{acc['id']}` — {acc['display']}{acc['marker']}")

        lines.append("")
        lines.append(
            "To switch, tell me which account number you want to use "
            "and I'll call `switch_account_to(account_id='...')`."
        )

        return "\n".join(lines)

    except Exception as e:
        logger.error(f"switch_account failed: {e}", exc_info=True)
        return f"❌ Failed to list accounts: {e}"
    finally:
        await client.close()


async def run_list_linkedin_accounts() -> str:
    """List connected LinkedIn accounts (read-only). Use switch_account to switch."""
    if not is_backend_mode():
        from ..config import get_unipile_config

        api_url, api_key = get_unipile_config()
        if not api_url or not api_key:
            return "❌ Not connected. Run setup_profile first."

    client = get_linkedin_client()
    try:
        accounts = await client.list_accounts()
        linkedin_accounts = []
        for acc in accounts:
            provider = (
                acc.get("provider")
                or acc.get("provider_type")
                or acc.get("type")
                or ""
            )
            if "LINKEDIN" not in str(provider).upper():
                continue
            acc_id = (
                acc.get("id")
                or acc.get("account_id")
                or acc.get("accountId")
                or acc.get("uuid")
            )
            if not acc_id:
                continue
            linkedin_accounts.append({"id": str(acc_id), "name": acc.get("name") or ""})

        if not linkedin_accounts:
            return (
                "No LinkedIn accounts connected.\n\n"
                "Run setup_profile() to connect your LinkedIn account."
            )

        current_id = get_account_id()
        lines = ["**Connected LinkedIn accounts:**\n"]
        for i, acc in enumerate(linkedin_accounts, 1):
            marker = " ← current" if acc["id"] == current_id else ""
            lines.append(f"{i}. `{acc['id']}` — {acc['name'] or 'LinkedIn account'}{marker}")
        lines.append("")
        lines.append("Use switch_account_to(account_id='...') to switch. Use unlink_account() to disconnect.")
        return "\n".join(lines)
    except Exception as e:
        logger.error(f"list_linkedin_accounts failed: {e}", exc_info=True)
        return f"❌ Failed to list accounts: {e}"
    finally:
        await client.close()


async def run_switch_account_to(account_id: str) -> str:
    """Switch to a specific LinkedIn account, re-fetch profile, re-analyze voice."""
    if not account_id or not account_id.strip():
        return "❌ Please provide an account_id."

    client = get_linkedin_client()
    try:
        # Verify the account exists and is connected
        connected, status_msg = await client.verify_account(account_id)
        if not connected:
            return f"❌ Account `{account_id}` is not connected: {status_msg}"

        # Store the new account ID
        save_setting("unipile_account_id", account_id)

        # Bind on backend too (if backend mode)
        if is_backend_mode():
            try:
                await client.bind_account(account_id)
            except Exception:
                pass  # 409 = already bound, which is fine

        # Fetch profile
        try:
            profile = await client.get_own_profile(account_id)
        except Exception as e:
            save_setting("unipile_account_id", account_id)  # keep it stored anyway
            return (
                f"✅ Switched to account `{account_id}` but couldn't fetch profile: {e}\n"
                "Run setup_profile() to retry."
            )

        if not profile.get("name"):
            return (
                f"✅ Switched to account `{account_id}` but profile is empty.\n"
                "The connection might need time to sync. Try setup_profile() in a minute."
            )

        # 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:
            profile["posts"] = []

        # Re-analyze voice
        try:
            analysis = await analyze_voice(profile)
        except Exception as e:
            # Store profile even if voice analysis fails
            save_setting("profile", profile)
            return (
                f"✅ Switched to account `{account_id}` — {profile['name']}\n"
                f"⚠️ Voice analysis failed: {e}\n"
                "Run setup_profile() to retry."
            )

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

        # Store everything
        save_setting("profile", profile)
        save_setting("voice_signature", voice)
        save_setting("expertise_map", expertise)
        save_setting("setup_complete", True)

        # Format output
        output = format_voice_signature(voice, expertise)

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

        return header + output

    except Exception as e:
        logger.error(f"switch_account_to failed: {e}", exc_info=True)
        return f"❌ Switch failed: {e}"
    finally:
        await client.close()
