'''
Macos utils for simple things in other OSes, such as: finding anything in
/Applications/
'''

import os
import plistlib
from opencos import eda_config
from opencos.utils import subprocess_helpers

IS_MACOS = subprocess_helpers.IS_MACOS

def get_macos_tool_info( # pylint: disable=dangerous-default-value
        app_name: str, prefer_exes: list = []
) -> dict:
    """
    Resolves the actual binary path and version from a macOS .app bundle.
    app_name: e.g., 'Visual Studio Code.app'

    Will look in:
      -- $HOME/Applications/
      -- /Applications/
    """
    ret = {}
    if not IS_MACOS:
        return ret

    if not app_name.endswith('.app'):
        app_name += '.app'

    # Try $HOME/Applications first.
    home = os.environ.get('HOME', '')
    if home:
        base_path = os.path.join(home, '/Applications', app_name)

    if not os.path.exists(base_path):
        # If not in $HOME/Applications, try /Applications:
        base_path = os.path.join('/Applications', app_name)

    plist_path = os.path.join(base_path, 'Contents/Info.plist')

    ret.update({
        'base_path': {
            'value': base_path,
            'exists': os.path.exists(base_path)
        },
        'plist_path': {
            'value': plist_path,
            'exists': os.path.exists(plist_path)
        }
    })

    if not os.path.exists(plist_path):
        return ret

    with open(plist_path, 'rb') as f:
        info = plistlib.load(f)

    # 1. Resolve Executable (Replaces shutil.which)
    exe_name = info.get('CFBundleExecutable')
    exe_path = os.path.join(base_path, 'Contents/MacOS', exe_name)

    # 2. Resolve Version (Standard macOS way)
    version = info.get('CFBundleShortVersionString', 'Unknown')

    # 3. Custom Metadata (Your product.json)
    # Usually in Resources, but could be in Contents
    product_json_path = os.path.join(base_path, 'Contents/Resources/product.json')
    if not os.path.exists(product_json_path):
        # we can try Contents/Resources/app/product.json:
        product_json_path = os.path.join(
            base_path, 'Contents/Resources/app/product.json')

    alt_bin_path = os.path.join(base_path, 'Contents/Resources/bin')
    if not os.path.isdir(alt_bin_path):
        alt_bin_path = os.path.join(base_path, 'Contents/Resources/app/bin')

    ret.update({
        'product_json_path': {
            'value': product_json_path,
            'exists': os.path.exists(product_json_path)
        },
        'alt_bin_path': {
            'value': alt_bin_path,
            'exists': os.path.isdir(alt_bin_path)
        }
    })

    if alt_bin_path:
        for prefer_exe in reversed(prefer_exes):
            prefer_exe_path = os.path.join(alt_bin_path, os.path.split(prefer_exe)[1])
            if os.path.exists(prefer_exe_path):
                exe_path = prefer_exe_path

    ret.update({
        "bin": exe_path,
        "version": version,
        "metadata": product_json_path if os.path.exists(product_json_path) else ''
    })
    return ret


def get_tool_exe_from_config(config: dict, tool: str) -> str:
    '''Returns the macos /Applications/ exe path using 'tool'

    Also will look at $HOME/Applications (using get_macos_tool_info(str))

    If no macos, reverts to the first exe in config.
    tool -- this is the opencos-eda tool name, such as 'verilator',
    from the --tool=TOOL arg, or auto-found.
    '''

    tool_cfg = config.get('tools', {}).get(tool, {})
    exe_list = eda_config.tool_get_exe_list(tool=tool, config=config)
    first_exe = exe_list[0]

    if IS_MACOS:
        app_name = tool_cfg.get('macos-app-name', '')
        if not app_name:
            app_name = tool_cfg.get('app-name', '')
        if not app_name:
            app_name = tool_cfg.get('windows-app-name', '')
        prefer_exes = tool_cfg.get('macos-prefer-exes', [])
        if exe_list:
            prefer_exes = exe_list + prefer_exes
        if app_name:
            data = get_macos_tool_info(app_name, prefer_exes=prefer_exes)
            if e := data.get('bin', ''):
                first_exe = e

    return first_exe
