"""connect_lma tool -- authorize the CloudSense LMA org.

This is the entry point for the LMA-first customer discovery flow.
It authorizes the License Management App (LMA) Salesforce org.
Field discovery via describe is best-effort -- if the Metadata API
is not accessible (profile restrictions, etc.), downstream tools
query sfLma objects directly via SOQL/SOSL which may still work.
"""

import logging
from typing import Any

from ..utils import sf_cli, state

logger = logging.getLogger(__name__)

DEFAULT_LMA_ALIAS = "cs-lma"
DEFAULT_LMA_LOGIN_URL = "https://login.salesforce.com"

SFLMA_OBJECTS_TO_DESCRIBE = [
    "sfLma__License__c",
    "sfLma__Package__c",
    "sfLma__Package_Version__c",
]

TOOL_DEFINITION = {
    "name": "connect_lma",
    "description": (
        "Authorize the CloudSense License Management App (LMA) Salesforce org. "
        "This is the FIRST tool to call for any customer inquiry -- it connects "
        "to the LMA org where all customer licenses, packages, and subscriber "
        "information are managed. Optionally discovers the sfLma field model "
        "(best-effort -- does not block if Metadata API is restricted). "
        "Stores the LMA org alias in state for use by all downstream tools."
    ),
    "inputSchema": {
        "type": "object",
        "properties": {
            "org_alias": {
                "type": "string",
                "description": (
                    "Alias for the LMA org. Defaults to 'cs-lma'. "
                    "If the org is already authorized under this alias, "
                    "the tool skips login."
                ),
            },
            "instance_url": {
                "type": "string",
                "description": (
                    "Salesforce login URL for the LMA org. "
                    "Defaults to 'https://login.salesforce.com'. "
                    "Override if the LMA org uses a custom domain "
                    "(e.g., 'https://cloudsense.my.salesforce.com/')."
                ),
            },
            "working_directory": {
                "type": "string",
                "description": (
                    "Workspace directory for state and output files. "
                    "The AI passes this automatically."
                ),
            },
        },
        "required": [],
    },
}


def _find_lma_org(alias: str) -> dict[str, Any] | None:
    """Check if an org with the given alias is already authorized."""
    try:
        orgs = sf_cli.list_orgs()
        for org in orgs:
            if org.get("alias") == alias:
                return org
    except sf_cli.SfCliError:
        pass
    return None


def _validate_org(alias: str) -> dict[str, Any] | None:
    """Validate that the org is still accessible."""
    try:
        data = sf_cli.display_org(alias)
        return data.get("result", {})
    except sf_cli.SfCliError:
        return None


def _describe_lma_objects(
    alias: str,
) -> dict[str, list[str]]:
    """Discover field names on sfLma objects by running sf sobject describe.

    Returns a dict mapping object API name to a list of field API names.
    On failure for an object, stores an empty list (graceful degradation).
    """
    fields_by_object: dict[str, list[str]] = {}
    for obj_name in SFLMA_OBJECTS_TO_DESCRIBE:
        try:
            desc = sf_cli.describe_sobject(obj_name, alias)
            field_list = desc.get("fields", [])
            fields_by_object[obj_name] = [
                f.get("name", "") for f in field_list if f.get("name")
            ]
            logger.info(
                "Discovered %d fields on %s",
                len(fields_by_object[obj_name]),
                obj_name,
            )
        except sf_cli.SfCliError as e:
            logger.warning("Could not describe %s: %s", obj_name, e)
            fields_by_object[obj_name] = []
    return fields_by_object


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

    report: list[str] = []
    report.append("# Connect to CloudSense LMA Org\n")

    # ── 1. Check if already authorized ──────────────────────────
    report.append("## Authorization\n")

    org_info = _validate_org(alias)
    if org_info:
        username = org_info.get("username", "unknown")
        org_id = org_info.get("id", "unknown")
        instance = org_info.get("instanceUrl", "unknown")
        report.append(f"- LMA org already authorized as **{alias}**")
        report.append(f"- Username: {username}")
        report.append(f"- Org ID: {org_id}")
        report.append(f"- Instance: {instance}")
    else:
        login_url = instance_url or DEFAULT_LMA_LOGIN_URL
        report.append(f"- LMA org '{alias}' is not yet authorized.")
        report.append(f"- Opening browser for login ({login_url})...")

        try:
            sf_cli.run_sf(
                f"org login web --alias {alias} --instance-url {login_url}",
                timeout=300,
                json_output=False,
            )
            report.append("- Browser login completed successfully.")
        except sf_cli.SfCliError as e:
            report.append(f"- Login failed: {e}")
            report.append(
                f"\nIf the browser did not open, run manually:\n"
                f"  ```\n"
                f"  sf org login web --alias {alias} "
                f"--instance-url {login_url}\n"
                f"  ```"
            )
            report.append("\n## STATUS: ACTION REQUIRED\n")
            report.append(
                "Login failed. Resolve the issue and call connect_lma again."
            )
            return "\n".join(report)

        org_info = _validate_org(alias)
        if not org_info:
            report.append("- Login appeared to succeed but org validation failed.")
            report.append("\n## STATUS: ACTION REQUIRED\n")
            report.append("Call connect_lma again to retry.")
            return "\n".join(report)

        username = org_info.get("username", "unknown")
        org_id = org_info.get("id", "unknown")
        instance = org_info.get("instanceUrl", "unknown")
        report.append(f"- Authorized as: {username}")
        report.append(f"- Org ID: {org_id}")
        report.append(f"- Instance: {instance}")

    # ── 2. Best-effort field discovery ────────────────────────────
    report.append("\n## sfLma Data Model Discovery (best-effort)\n")

    lma_fields = _describe_lma_objects(alias)

    has_fields = False
    for obj_name, fields in lma_fields.items():
        if fields:
            has_fields = True
            report.append(f"- **{obj_name}**: {len(fields)} fields discovered")
        else:
            report.append(
                f"- **{obj_name}**: describe unavailable "
                f"(Metadata API may be restricted)"
            )

    if not has_fields:
        report.append(
            "\nNote: Field discovery via Metadata API was not possible. "
            "This is normal if your profile does not have Metadata API "
            "access. Downstream tools will query sfLma objects directly "
            "via SOQL/SOSL, which typically works regardless."
        )

    # ── 3. Persist to state (creates file if it doesn't exist) ──
    state.ensure_state(
        lma_org_alias=alias,
        lma_org_username=org_info.get("username", ""),
        lma_org_id=org_info.get("id", ""),
        lma_fields={k: v for k, v in lma_fields.items()},
    )
    report.append("\n## State\n")
    report.append("- LMA org info saved to state file")
    if has_fields:
        report.append("- sfLma field lists saved for downstream tools")
    else:
        report.append(
            "- No field lists available (downstream tools will "
            "use default field lists)"
        )

    # ── 4. Summary ──────────────────────────────────────────────
    report.append("\n---\n")
    report.append("## STATUS: READY\n")
    report.append(
        f"LMA org connected as '{alias}'.\n\n"
        f"Next step: call **find_customer** with a customer name "
        f"to search the LMA org, or call **get_portfolio_insights** "
        f"for a cross-customer analysis."
    )

    return "\n".join(report)
