"""connect_lma -- Authorize the CloudSense License Management Portal.

Entry point for the workflow. Checks if the LMA org is already
authorized via sf org display, then sf org list. If neither works,
opens browser login with a safe timeout. After auth, validates the
org is actually a CloudSense LMA org by probing sfLma__Package__c.
"""

import logging
import os
import signal
import subprocess
import sys
from typing import Any

from ..utils import sf_cli, state

logger = logging.getLogger(__name__)

DEFAULT_ALIAS = "cs-lma"
DEFAULT_LOGIN_URL = "https://login.salesforce.com"
LOGIN_TIMEOUT_SECONDS = 60

TOOL_DEFINITION = {
    "name": "connect_lma",
    "description": (
        "Authorize the CloudSense License Management Portal. "
        "This is the FIRST tool to call for any customer inquiry. "
        "Checks if the LMA org is already authorized, opens browser "
        "login if not. Validates the org contains CloudSense LMA data. "
        "Call again after the user completes login."
    ),
    "inputSchema": {
        "type": "object",
        "properties": {
            "org_alias": {
                "type": "string",
                "description": (
                    "Alias for the LMA org. Defaults to 'cs-lma'. "
                    "If already authorized under this alias, login is skipped."
                ),
            },
            "instance_url": {
                "type": "string",
                "description": (
                    "Salesforce login URL. Defaults to "
                    "'https://login.salesforce.com'. Override for custom domains."
                ),
            },
            "working_directory": {
                "type": "string",
                "description": "Workspace directory. The AI passes this automatically.",
            },
        },
        "required": [],
    },
}


def _validate_org(alias: str) -> dict[str, Any] | None:
    """Check if an org is authorized and accessible."""
    try:
        data = sf_cli.display_org(alias)
        return data.get("result", {})
    except sf_cli.SfCliError:
        return None


def _find_org_in_list(alias: str) -> dict[str, Any] | None:
    """Search sf org list for an org matching the alias or username."""
    try:
        orgs = sf_cli.list_orgs()
        alias_lower = alias.lower()
        for org in orgs:
            org_alias = (org.get("alias") or "").lower()
            org_user = (org.get("username") or "").lower()
            if alias_lower in org_alias or alias_lower in org_user:
                return org
    except sf_cli.SfCliError:
        pass
    return None


def _is_lma_org(alias: str) -> bool:
    """Verify the org has sfLma__Package__c — i.e. it's a real LMA org."""
    try:
        sf_cli.lma_query(
            "SELECT Id FROM sfLma__Package__c LIMIT 1", alias
        )
        return True
    except sf_cli.SfCliError:
        return False


def _kill_port_1717() -> bool:
    """Kill any process listening on port 1717 (stale OAuth server)."""
    try:
        if sys.platform == "win32":
            result = subprocess.run(
                ["netstat", "-ano"],
                capture_output=True, text=True, timeout=5,
            )
            killed = False
            for line in result.stdout.splitlines():
                if ":1717 " in line and "LISTENING" in line:
                    parts = line.split()
                    pid = parts[-1]
                    subprocess.run(
                        ["taskkill", "/PID", pid, "/F"],
                        capture_output=True, timeout=5,
                    )
                    logger.info("Killed stale process %s on port 1717", pid)
                    killed = True
            return killed
        else:
            result = subprocess.run(
                ["lsof", "-ti", ":1717"],
                capture_output=True, text=True, timeout=5,
            )
            pids = result.stdout.strip().split()
            if not pids or pids == [""]:
                return False
            for pid in pids:
                try:
                    os.kill(int(pid), signal.SIGKILL)
                    logger.info("Killed stale process %s on port 1717", pid)
                except (ValueError, OSError):
                    pass
            return True
    except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
        return False


def _try_browser_login(alias: str, login_url: str) -> str | None:
    """Open browser login with a safe timeout.

    Returns None on success, or a conversational message for the AI.
    Automatically clears stale port 1717 conflicts and retries once.
    """
    max_attempts = 2
    for attempt in range(1, max_attempts + 1):
        try:
            sf_cli.run_sf(
                f"org login web --alias {alias} --instance-url {login_url}",
                timeout=LOGIN_TIMEOUT_SECONDS,
                json_output=False,
            )
            return None
        except sf_cli.SfCliError as e:
            error_str = str(e)

            if "1717" in error_str and attempt < max_attempts:
                logger.info("Port 1717 conflict detected, killing stale process and retrying")
                _kill_port_1717()
                continue

            if "TimeoutExpired" in str(e.stderr):
                _kill_port_1717()
                return (
                    "STATUS: LOGIN_TIMEOUT\n\n"
                    "The browser was opened for Salesforce login but the user "
                    "did not complete authorization in time.\n\n"
                    "Tell the user: \"It looks like the login wasn't completed "
                    "in time. Would you like to try again? If the browser is "
                    "still open, you can finish logging in there and I'll "
                    "retry the connection.\"\n\n"
                    "If the user wants to try manually, they can run:\n"
                    f"sf org login web --alias {alias} --instance-url {login_url}\n\n"
                    "Call connect_lma again once the user is ready."
                )

            return (
                "STATUS: LOGIN_FAILED\n\n"
                f"Browser login failed with error: {e}\n\n"
                "Tell the user: \"The login didn't go through. Would you "
                "like to try again, or would you prefer to run the login "
                "command manually in your terminal?\"\n\n"
                "Manual command:\n"
                f"sf org login web --alias {alias} --instance-url {login_url}\n\n"
                "Call connect_lma again once the user is ready."
            )
    return None


async def run(arguments: dict[str, Any]) -> str:
    """Execute the connect_lma tool."""
    state.set_working_dir(arguments.get("working_directory"))

    sf_check = sf_cli.check_sf_installed()
    if not sf_check["installed"]:
        return (
            "STATUS: SF_CLI_MISSING\n\n"
            "Salesforce CLI (sf) was not found. Auto-detection checked PATH "
            "and common install locations (Program Files, npm, Chocolatey, Scoop).\n\n"
            "If the user has sf installed (verified via terminal), it is likely "
            "a PATH inheritance issue. Guide the user to:\n"
            "1. Run 'sf org login web --alias cs-lma' in their own terminal\n"
            "2. Then call connect_lma again to pick up the authorized org\n\n"
            "If that also fails, ask the user to restart Cursor to refresh PATH.\n\n"
            "Install link: https://developer.salesforce.com/tools/salesforcecli"
        )

    alias = arguments.get("org_alias") or DEFAULT_ALIAS
    login_url = arguments.get("instance_url") or DEFAULT_LOGIN_URL

    org_info = _validate_org(alias)

    if not org_info:
        found = _find_org_in_list(alias)
        if found:
            real_alias = found.get("alias") or found.get("username") or alias
            org_info = _validate_org(real_alias)
            if org_info:
                alias = real_alias

    if not org_info:
        error_msg = _try_browser_login(alias, login_url)
        if error_msg:
            return error_msg

        org_info = _validate_org(alias)
        if not org_info:
            return (
                "STATUS: LOGIN_VALIDATION_FAILED\n\n"
                "Login appeared to succeed but the org could not be "
                "verified afterwards.\n\n"
                "Tell the user: \"The login seemed to go through but "
                "I couldn't verify the connection. Would you like to "
                "try again?\"\n\n"
                "Call connect_lma again to retry."
            )

    username = org_info.get("username", "unknown")
    org_id = org_info.get("id", "unknown")
    instance = org_info.get("instanceUrl", "unknown")

    if not _is_lma_org(alias):
        return (
            "STATUS: WRONG_ORG\n\n"
            f"Connected to org **{username}** ({instance}) but it does "
            f"not appear to be a CloudSense LMA org — the "
            f"sfLma__Package__c object was not found.\n\n"
            "Tell the user: \"The org you logged into doesn't appear to "
            "be the CloudSense License Management Portal. It's missing "
            "the LMA package (sfLma). Could you double-check you're "
            "logging into the correct org? Would you like to try again "
            "with a different org or login URL?\"\n\n"
            "To retry with a different org, call connect_lma with a "
            "different org_alias or instance_url.\n\n"
            "To clear this auth and try fresh:\n"
            f"sf org logout --target-org {alias} --no-prompt\n"
            f"sf org login web --alias {alias} --instance-url {login_url}"
        )

    state.update(lma_org_alias=alias)

    return (
        "STATUS: CONNECTED\n\n"
        f"- **Alias:** {alias}\n"
        f"- **Username:** {username}\n"
        f"- **Org ID:** {org_id}\n"
        f"- **Instance:** {instance}\n\n"
        "LMA org verified — sfLma__Package__c is accessible.\n"
        "Tell the user the LMA connection is ready."
    )
