"""
Read-only MCP tools for Salesforce workflows.
"""

from __future__ import annotations

from pathlib import Path
from typing import Any, Callable, Dict, List, Tuple

from g_gremlin import sfdc as sfdc_helpers
from g_gremlin import sfdc_dedupe_workflow
from g_gremlin import sfdc_snapshot as sfdc_snapshot_mod
from g_gremlin.sfdc_metadata_components import MetadataType, scan_source_dir
from g_gremlin.sfdc_metadata_manifest import generate_package_xml

ToolTuple = Tuple[str, Callable[..., Dict[str, Any]], str]


def _resolved_target(target: str | None) -> str | None:
    return target or sfdc_helpers.get_configured_org()


def sfdc_whoami(target: str | None = None) -> Dict[str, Any]:
    resolved_target = _resolved_target(target)
    return {"identity": sfdc_helpers.get_org_identity(org_alias=resolved_target)}


def sfdc_doctor(target: str | None = None) -> Dict[str, Any]:
    resolved_target = _resolved_target(target)
    checks: List[Dict[str, Any]] = []
    status = "ok"
    try:
        version = sfdc_helpers.get_cli_version()
        checks.append({"name": "sf_cli", "status": "ok", "detail": version})
    except Exception as exc:
        checks.append({"name": "sf_cli", "status": "error", "detail": str(exc)})
        status = "error"

    for name, path in (
        ("data_query", ["data", "query"]),
        ("data_update_record", ["data", "update", "record"]),
    ):
        try:
            available = sfdc_helpers.check_command_available(path)
            checks.append(
                {
                    "name": name,
                    "status": "ok" if available else "warn",
                    "detail": "available" if available else "not found",
                }
            )
            if not available and status == "ok":
                status = "warn"
        except Exception as exc:
            checks.append({"name": name, "status": "warn", "detail": str(exc)})
            if status == "ok":
                status = "warn"

    try:
        describe_cmd = sfdc_helpers.get_describe_command_path()
        if describe_cmd:
            checks.append(
                {
                    "name": "schema_describe",
                    "status": "ok",
                    "detail": f"available ({' '.join(describe_cmd)})",
                }
            )
        else:
            checks.append({"name": "schema_describe", "status": "warn", "detail": "not found"})
            if status == "ok":
                status = "warn"
    except Exception as exc:
        checks.append({"name": "schema_describe", "status": "warn", "detail": str(exc)})
        if status == "ok":
            status = "warn"

    try:
        identity = sfdc_helpers.get_org_identity(org_alias=resolved_target)
    except Exception as exc:
        identity = {"error": str(exc)}
        status = "error"

    return {"status": status, "checks": checks, "identity": identity}


def sfdc_query(soql: str, target: str | None = None, limit: int | None = None) -> Dict[str, Any]:
    rows = sfdc_helpers.run_soql(soql, org_alias=_resolved_target(target))
    if limit is not None:
        rows = rows[: max(int(limit), 0)]
    return {"rows": rows, "count": len(rows)}


def sfdc_describe(sobject: str, target: str | None = None, fields_only: bool = False) -> Dict[str, Any]:
    payload = sfdc_helpers.describe_sobject(sobject, org_alias=_resolved_target(target))
    if fields_only:
        result = payload.get("result") or {}
        return {"result": {"fields": result.get("fields") or []}}
    return payload


def sfdc_snapshot(
    out_dir: str,
    target: str | None = None,
    object_name: str | None = None,
    fields: List[str] | None = None,
    where: str | None = None,
    order_by: str | None = None,
    limit: int | None = None,
    include_schema: bool = False,
) -> Dict[str, Any]:
    if not object_name or not fields:
        raise ValueError("object_name and fields are required for sfdc.snapshot.")
    spec = {
        "version": 1,
        "objects": [
            {
                "name": object_name,
                "fields": list(fields),
                "where": where,
                "order_by": order_by,
                "limit": limit,
            }
        ],
    }
    result = sfdc_snapshot_mod.snapshot(
        Path(out_dir),
        spec=spec,
        org_alias=_resolved_target(target),
        include_schema=include_schema,
    )
    return result.to_dict()


def sfdc_audit(csv_path: str, id_column: str, sobject: str, target: str | None = None) -> Dict[str, Any]:
    return sfdc_helpers.audit_ids(Path(csv_path), id_column, sobject, org_alias=_resolved_target(target))


def sfdc_reports_list(target: str | None = None) -> Dict[str, Any]:
    rows = sfdc_helpers.list_reports(org_alias=_resolved_target(target))
    return {"count": len(rows), "reports": rows}


def sfdc_manifest_generate(
    source_dir: str,
    api_version: str = "62.0",
    include_types: List[str] | None = None,
) -> Dict[str, Any]:
    include = None
    if include_types:
        include = set()
        for token in include_types:
            raw = str(token or "").strip().lower()
            if not raw:
                continue
            match = next(
                (mtype for mtype in MetadataType if raw in {mtype.value.lower(), mtype.name.lower()}),
                None,
            )
            if match is None:
                raise ValueError(f"Unknown metadata type: {token}")
            include.add(match)

    inventory = scan_source_dir(Path(source_dir), include=include)
    xml_text = generate_package_xml(inventory.components, api_version)
    return {
        "component_count": len(inventory.components),
        "types": sorted({comp.type.value for comp in inventory.components}),
        "package_xml": xml_text,
    }


def sfdc_dedupe_preflight(target: str | None = None) -> Dict[str, Any]:
    return sfdc_dedupe_workflow.dedupe_preflight(target=target)


def get_tools() -> List[ToolTuple]:
    return [
        ("sfdc.whoami", sfdc_whoami, "Return authenticated Salesforce identity."),
        ("sfdc.doctor", sfdc_doctor, "Check Salesforce CLI and auth health."),
        ("sfdc.query", sfdc_query, "Run a SOQL query and return rows."),
        ("sfdc.describe", sfdc_describe, "Describe a Salesforce SObject."),
        ("sfdc.snapshot", sfdc_snapshot, "Create a deterministic Salesforce snapshot."),
        ("sfdc.audit", sfdc_audit, "Audit IDs in a CSV against Salesforce."),
        ("sfdc.reports.list", sfdc_reports_list, "List Salesforce reports."),
        ("sfdc.manifest_generate", sfdc_manifest_generate, "Generate package.xml from source."),
        ("sfdc.dedupe.preflight", sfdc_dedupe_preflight, "Check Salesforce dedupe prerequisites and convertLead capability."),
    ]
