"""
Retrieve Salesforce metadata components via sf CLI.
"""

from __future__ import annotations

import tempfile
from pathlib import Path
from typing import Iterable, List, Optional

from g_gremlin import sfdc as sfdc_helpers
from g_gremlin.sfdc_metadata_components import MetadataComponent
from g_gremlin.sfdc_metadata_manifest import write_package_xml


DEFAULT_METADATA_THRESHOLD = 20


def retrieve_components(
    components: Iterable[MetadataComponent],
    output_dir: Path,
    org_alias: Optional[str] = None,
    *,
    api_version: str | None = None,
    metadata_threshold: int = DEFAULT_METADATA_THRESHOLD,
) -> dict:
    component_list = list(components)
    if not component_list:
        return {"status": "skipped", "reason": "no_components"}

    output_dir.mkdir(parents=True, exist_ok=True)

    if len(component_list) <= metadata_threshold:
        metadata_arg = _metadata_arg(component_list)
        return sfdc_helpers.project_retrieve_start(
            metadata=metadata_arg,
            output_dir=output_dir,
            org_alias=org_alias,
        )

    with tempfile.TemporaryDirectory() as tmpdir:
        manifest_path = Path(tmpdir) / "package.xml"
        write_package_xml(manifest_path, component_list, api_version or "59.0")
        return retrieve_by_package_xml(manifest_path, output_dir, org_alias=org_alias)


def retrieve_by_package_xml(
    package_xml_path: Path,
    output_dir: Path,
    org_alias: Optional[str] = None,
) -> dict:
    output_dir.mkdir(parents=True, exist_ok=True)
    return sfdc_helpers.project_retrieve_start(
        manifest=package_xml_path,
        output_dir=output_dir,
        org_alias=org_alias,
    )


def list_org_metadata(metadata_type: str, org_alias: Optional[str] = None) -> List[dict]:
    return list(sfdc_helpers.org_list_metadata(metadata_type, org_alias=org_alias) or [])


def _metadata_arg(components: List[MetadataComponent]) -> str:
    parts: List[str] = []
    for comp in components:
        parts.append(f"{comp.type.value}:{comp.member_name}")
    return ",".join(parts)
