"""
macOS platform startup layer.

Extracted from ws_engine.py. All functions accept ``logger`` as their first
parameter so callers can pass their own logger rather than relying on a module-
level global.
"""

import ctypes
import os
import platform
import shutil
import stat
import subprocess
import sys
import threading
import time
from pathlib import Path

# ---------------------------------------------------------------------------
# Module-level state
# ---------------------------------------------------------------------------

# Cache for screen-recording permission checks (avoids hammering WindowServer).
# Structure mirrors the original in ws_engine.py.
_permission_cache: dict = {
    "screen_recording": None,
    "last_check_time": 0,
    "cache_ttl": 30,  # seconds
}

# Guard so start_permission_monitor() is idempotent.
_permission_monitor_started: bool = False

# Canonical install location (must match PKG postinstall, setup_macos, Electron spawn).
CANONICAL_APP_SUPPORT = Path.home() / "Library" / "Application Support" / "Workstatus"
CANONICAL_APP_BUNDLE = CANONICAL_APP_SUPPORT / "Workstatus.app"
BUNDLE_IDENTITY_MARKER = CANONICAL_APP_SUPPORT / ".screen_capture_bundle_identity"

_CORE_GRAPHICS = None


def get_canonical_app_bundle_path() -> Path:
    """Return the single install path used for TCC / Screen Recording grants."""
    return CANONICAL_APP_BUNDLE


def get_running_app_bundle_path() -> Path | None:
    """Return the .app bundle path for the current process, if frozen on macOS."""
    if platform.system() != "Darwin" or not getattr(sys, "frozen", False):
        return None
    try:
        exe_dir = Path(sys.executable).resolve().parent
        bundle = exe_dir.parent.parent
        if bundle.suffix == ".app" and bundle.exists():
            return bundle
    except Exception:
        pass
    return None


def _load_core_graphics():
    global _CORE_GRAPHICS
    if _CORE_GRAPHICS is not None:
        return _CORE_GRAPHICS
    if platform.system() != "Darwin":
        return None
    try:
        _CORE_GRAPHICS = ctypes.CDLL(
            "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics"
        )
    except OSError:
        _CORE_GRAPHICS = False
    return _CORE_GRAPHICS


def invalidate_screen_recording_cache(logger=None) -> None:
    """Clear cached Screen Recording state (e.g. after install or signature change)."""
    _permission_cache["screen_recording"] = None
    _permission_cache["last_check_time"] = 0
    if logger:
        logger.debug("[PERMISSIONS] Screen Recording permission cache cleared")


def _read_bundle_code_identity(app_bundle: Path) -> str | None:
    """Fingerprint the signed bundle so TCC can be re-checked after upgrades."""
    if not app_bundle.is_dir():
        return None
    try:
        result = subprocess.run(
            ["codesign", "-dv", str(app_bundle)],
            capture_output=True,
            text=True,
            timeout=10,
        )
        blob = (result.stderr or "") + (result.stdout or "")
        parts = []
        for line in blob.splitlines():
            stripped = line.strip()
            if stripped.startswith("CDHash=") or stripped.startswith("TeamIdentifier="):
                parts.append(stripped)
        return "|".join(parts) if parts else None
    except Exception:
        return None


def sync_bundle_identity_and_maybe_invalidate(logger) -> bool:
    """
    If the running bundle's code signature changed (new build), invalidate the
    Screen Recording cache so we do not treat a stale TCC grant as active.

    Returns True when identity changed since last run.
    """
    bundle = get_running_app_bundle_path()
    if bundle is None:
        return False

    identity = _read_bundle_code_identity(bundle)
    if not identity:
        return False

    previous = None
    try:
        if BUNDLE_IDENTITY_MARKER.is_file():
            previous = BUNDLE_IDENTITY_MARKER.read_text(encoding="utf-8").strip()
    except OSError as e:
        logger.debug("[PERMISSIONS] Could not read bundle identity marker: %s", e)

    try:
        CANONICAL_APP_SUPPORT.mkdir(parents=True, exist_ok=True)
        BUNDLE_IDENTITY_MARKER.write_text(identity, encoding="utf-8")
    except OSError as e:
        logger.debug("[PERMISSIONS] Could not write bundle identity marker: %s", e)

    if previous and previous != identity:
        logger.info(
            "[PERMISSIONS] New app build detected (signature changed) — re-validating Screen Recording"
        )
        invalidate_screen_recording_cache(logger)
        return True
    return False


def _cg_preflight_screen_capture() -> bool | None:
    """
    Use macOS CoreGraphics API for authoritative Screen Recording state.
    Returns None if the API is unavailable (fall back to ImageGrab probe).
    """
    cg = _load_core_graphics()
    if not cg or cg is False:
        return None
    if not hasattr(cg, "CGPreflightScreenCaptureAccess"):
        return None
    try:
        cg.CGPreflightScreenCaptureAccess.restype = ctypes.c_bool
        return bool(cg.CGPreflightScreenCaptureAccess())
    except Exception:
        return None


def _cg_request_screen_capture() -> bool | None:
    """Trigger the system Screen Recording prompt when not yet granted."""
    cg = _load_core_graphics()
    if not cg or cg is False:
        return None
    if not hasattr(cg, "CGRequestScreenCaptureAccess"):
        return None
    try:
        cg.CGRequestScreenCaptureAccess.restype = ctypes.c_bool
        return bool(cg.CGRequestScreenCaptureAccess())
    except Exception:
        return None


def _image_grab_indicates_screen_recording(logger) -> bool:
    """
    Fallback when CGPreflight is unavailable.

    Without Screen Recording, macOS often returns a valid-sized but all-black grab.
    """
    try:
        from PIL import ImageGrab  # type: ignore
    except ImportError:
        return False

    try:
        test_image = ImageGrab.grab(bbox=(0, 0, 32, 32))
    except OSError as e:
        logger.debug("[PERMISSIONS] Screen Recording probe failed (OSError): %s", e)
        return False
    except Exception as e:
        logger.debug("[PERMISSIONS] Screen Recording probe failed: %s", e)
        return False

    if test_image is None or test_image.size[0] <= 0 or test_image.size[1] <= 0:
        return False

    try:
        rgb = test_image.convert("RGB")
        pixels = list(rgb.getdata())
        if not pixels:
            return False
        step = max(1, len(pixels) // 64)
        sample = pixels[::step]
        if all(p == (0, 0, 0) for p in sample):
            logger.debug("[PERMISSIONS] Screen grab is all black — Screen Recording not effective")
            return False
        if len(set(sample)) <= 1:
            logger.debug("[PERMISSIONS] Screen grab has no color variance — Screen Recording not effective")
            return False
        return True
    except Exception as e:
        logger.debug("[PERMISSIONS] Could not analyze screen grab: %s", e)
        return False


# ---------------------------------------------------------------------------
# 1. Application Support directory
# ---------------------------------------------------------------------------

def get_app_support_dir(logger) -> str:
    """
    Return (and create if necessary) ~/Library/Application Support/Workstatus/.

    Falls back to ~/Workstatus/ if the preferred path cannot be created.
    Raises OSError only if both paths fail.
    """
    app_support = os.path.expanduser("~/Library/Application Support/Workstatus")
    app_support_path = Path(app_support)

    try:
        app_support_path.mkdir(parents=True, exist_ok=True)

        # Belt-and-suspenders: use shell mkdir if Python's mkdir silently did nothing.
        if not app_support_path.exists():
            subprocess.run(["mkdir", "-p", str(app_support_path)], check=False)

        if not app_support_path.exists():
            raise OSError(f"Failed to create Application Support directory: {app_support}")

        # Non-fatal write test.
        test_file = app_support_path / ".write_test"
        try:
            test_file.write_text("test")
            test_file.unlink()
        except (PermissionError, OSError) as e:
            logger.warning("[WARN] Cannot write to Application Support directory %s: %s", app_support, e)
            try:
                subprocess.run(["chmod", "755", str(app_support_path)], check=False)
            except Exception:
                pass

        logger.info("[INFO] Application Support directory: %s", app_support_path)
        logger.info("[INFO] To view in Finder: press Cmd+Shift+G and paste: %s", app_support_path.parent)
        return str(app_support_path)

    except OSError as e:
        logger.error("[ERROR] Failed to create Application Support directory: %s", e)

        # Fallback: ~/Workstatus/
        fallback_dir = Path.home() / "Workstatus"
        logger.info("[INFO] Attempting fallback to: %s", fallback_dir)
        try:
            fallback_dir.mkdir(parents=True, exist_ok=True)
            if fallback_dir.exists():
                logger.info("[INFO] Fallback directory created: %s", fallback_dir)
                return str(fallback_dir)
        except Exception as fallback_e:
            logger.error("[ERROR] Fallback creation failed: %s", fallback_e)

        raise


# ---------------------------------------------------------------------------
# 2. Quarantine removal
# ---------------------------------------------------------------------------

def remove_quarantine_attributes(target_path: Path, logger) -> None:
    """
    Recursively strip com.apple.quarantine xattrs from *target_path*.
    No-op on non-macOS or if the path does not exist.
    """
    if platform.system() != "Darwin":
        return

    if not target_path or not target_path.exists():
        return

    try:
        logger.info("[PERMISSIONS] Removing quarantine attributes from %s", target_path)
        subprocess.run(
            ["xattr", "-dr", "com.apple.quarantine", str(target_path)],
            check=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        logger.info("[PERMISSIONS] Quarantine attributes removed successfully")
    except FileNotFoundError:
        logger.warning("[PERMISSIONS] xattr command not found — cannot remove quarantine attributes automatically")
    except subprocess.CalledProcessError as e:
        logger.warning(
            "[PERMISSIONS] Could not remove quarantine attributes (non-fatal): %s",
            e.stderr.decode().strip() if e.stderr else e,
        )
    except Exception as e:
        logger.warning("[PERMISSIONS] Unexpected error removing quarantine attributes: %s", e)


# ---------------------------------------------------------------------------
# 3. Accessibility permission
# ---------------------------------------------------------------------------

def check_accessibility_permission() -> bool:
    """
    Return True if macOS Accessibility permission is granted, or if not macOS.
    Uses AXIsProcessTrusted via ctypes — no side-effects.
    """
    if platform.system() != "Darwin":
        return True

    try:
        _APP_SERVICES = "/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices"
        app_services = ctypes.CDLL(_APP_SERVICES)
        if hasattr(app_services, "AXIsProcessTrusted"):
            app_services.AXIsProcessTrusted.restype = ctypes.c_bool
            return bool(app_services.AXIsProcessTrusted())
        # API not present — conservatively report not-granted.
        return False
    except Exception:
        return False


# ---------------------------------------------------------------------------
# 4. Screen Recording permission (cached)
# ---------------------------------------------------------------------------

def check_screen_recording_permission(logger) -> bool:
    """
    Return True only when Screen Recording is actually effective for this process.

    Uses ``CGPreflightScreenCaptureAccess`` when available (matches System Settings).
    Falls back to an ImageGrab probe that rejects all-black placeholder frames.
    Results are cached for ``_permission_cache['cache_ttl']`` seconds (default 30s).
  """
    if platform.system() != "Darwin":
        return True

    current_time = time.time()
    cache_age = current_time - _permission_cache["last_check_time"]

    if _permission_cache["screen_recording"] is not None and cache_age < _permission_cache["cache_ttl"]:
        return _permission_cache["screen_recording"]

    preflight = _cg_preflight_screen_capture()
    if preflight is not None:
        result = preflight
        if not result:
            logger.debug("[PERMISSIONS] CGPreflightScreenCaptureAccess: not granted")
    else:
        result = _image_grab_indicates_screen_recording(logger)

    _permission_cache["screen_recording"] = result
    _permission_cache["last_check_time"] = current_time
    return result


# ---------------------------------------------------------------------------
# 5. Permission instructions dialog
# ---------------------------------------------------------------------------

def show_macos_permission_instructions(app_path: Path, logger) -> None:
    """
    Display an osascript dialog guiding the user to grant required permissions.
    No-op on non-macOS.
    """
    if platform.system() != "Darwin":
        return

    try:
        instruction = (
            "Workstatus needs Accessibility, Input Monitoring, and Screen Recording permissions.\n\n"
            "1. Open System Settings > Privacy & Security.\n"
            "2. Select Accessibility, Input Monitoring, and Screen Recording.\n"
            f"3. Click the '+' button and add:\n   {app_path}\n"
            "4. Enable the checkbox next to Workstatus.\n"
            "5. Quit Workstatus, reopen it, and log in again so permissions take effect.\n\n"
            "If Workstatus is already listed, remove it and add again from the path above."
        )
        escaped = instruction.replace('"', '\\"')
        subprocess.run(
            [
                "osascript",
                "-e",
                f'display dialog "{escaped}" buttons {{"OK"}} default button "OK" with icon caution',
            ],
            check=False,
        )
    except Exception as e:
        logger.warning("[PERMISSIONS] Could not show instruction dialog: %s", e)


# ---------------------------------------------------------------------------
# 6. Request macOS permissions
# ---------------------------------------------------------------------------

def request_macos_permissions(logger) -> None:
    """
    Request only permissions that are not already granted for this bundle.

    Uses CoreGraphics Screen Recording APIs when available so System Settings and
    runtime behavior stay aligned after upgrades.

    Should only be called after the app is in Application Support and a single
    instance is running.
    """
    if platform.system() != "Darwin":
        return

    bundle = get_running_app_bundle_path()
    canonical = get_canonical_app_bundle_path()
    if bundle is not None:
        try:
            if bundle.resolve() != canonical.resolve():
                logger.warning(
                    "[PERMISSIONS] App running from %s — expected %s (grant permissions for the running copy)",
                    bundle, canonical,
                )
        except Exception as path_error:
            logger.debug("[PERMISSIONS] Could not compare bundle paths: %s", path_error)

    sync_bundle_identity_and_maybe_invalidate(logger)
    invalidate_screen_recording_cache(logger)

    screen_ok = check_screen_recording_permission(logger)
    accessibility_ok = check_accessibility_permission()

    logger.info(
        "[PERMISSIONS] Permission state — Screen Recording: %s, Accessibility: %s",
        "granted" if screen_ok else "needed",
        "granted" if accessibility_ok else "needed",
    )

    try:
        macos_version = platform.mac_ver()[0]
        parts = macos_version.split(".")
        major_version = int(parts[0])
        minor_version = int(parts[1]) if len(parts) > 1 else 0
        is_system_settings = major_version >= 13
        is_macos_14_8 = major_version == 14 and minor_version == 8
        wait_time = 2.0 if is_macos_14_8 else 1.0

        # --- Screen Recording (only when not already effective) ---
        if not screen_ok:
            requested = _cg_request_screen_capture()
            if requested is True:
                logger.info("[PERMISSIONS] Screen Recording granted via system prompt")
                invalidate_screen_recording_cache(logger)
                screen_ok = check_screen_recording_permission(logger)
            elif requested is False:
                logger.info("[PERMISSIONS] Screen Recording prompt dismissed or denied")
            else:
                try:
                    from PIL import ImageGrab  # type: ignore

                    logger.info("[PERMISSIONS] Triggering Screen Recording via capture probe...")
                    ImageGrab.grab(bbox=(0, 0, 100, 100))
                except OSError as e:
                    logger.debug("[PERMISSIONS] Capture probe (expected without grant): %s", e)
                except ImportError:
                    logger.warning("[PERMISSIONS] PIL ImageGrab not available for Screen Recording test")
                except Exception as e:
                    logger.warning("[PERMISSIONS] Screen capture test error: %s", e)
                time.sleep(wait_time)
                invalidate_screen_recording_cache(logger)
                screen_ok = check_screen_recording_permission(logger)

            if not screen_ok and bundle is not None:
                show_macos_permission_instructions(bundle, logger)

        # --- Input Monitoring probes (no reliable preflight API) ---
        input_monitoring_ok = False
        try:
            from pynput import mouse, keyboard  # type: ignore

            try:
                test_mouse = mouse.Listener(
                    suppress=False,
                    on_move=lambda x, y: None,
                    on_click=lambda x, y, button, pressed: None,
                )
                test_mouse.start()
                time.sleep(wait_time)
                input_monitoring_ok = bool(test_mouse.running)
                test_mouse.stop()
            except Exception as e:
                logger.warning("[PERMISSIONS] Mouse listener test failed: %s", e)

            time.sleep(0.5)

            if not input_monitoring_ok:
                try:
                    test_keyboard = keyboard.Listener(
                        suppress=False,
                        on_press=lambda key: None,
                        on_release=lambda key: None,
                    )
                    test_keyboard.start()
                    time.sleep(wait_time)
                    input_monitoring_ok = bool(test_keyboard.running)
                    test_keyboard.stop()
                except Exception as e:
                    logger.warning("[PERMISSIONS] Keyboard listener test failed: %s", e)

        except ImportError:
            logger.warning("[PERMISSIONS] pynput not available for Input Monitoring permission testing")
        except Exception as e:
            logger.warning("[PERMISSIONS] Input Monitoring test error: %s", e)

        time.sleep(0.5)

        # --- Open only the settings panes still needed ---
        need_settings = (not screen_ok) or (not accessibility_ok) or (not input_monitoring_ok)
        if need_settings:
            if is_system_settings:
                logger.info("[PERMISSIONS] Opening System Settings for missing permissions...")
                if not accessibility_ok:
                    subprocess.Popen(
                        ["open", "x-apple.system-settings:com.apple.preference.security?Privacy_Accessibility"]
                    )
                    time.sleep(0.5)
                if not screen_ok:
                    subprocess.Popen(
                        ["open", "x-apple.system-settings:com.apple.preference.security?Privacy_ScreenCapture"]
                    )
                    time.sleep(0.5)
                if not input_monitoring_ok:
                    try:
                        subprocess.Popen(
                            [
                                "open",
                                "x-apple.system-settings:com.apple.preference.security?Privacy_InputMonitoring",
                            ]
                        )
                    except Exception:
                        subprocess.Popen(
                            [
                                "open",
                                "x-apple.system-settings:com.apple.preference.security?Privacy_ListenEvent",
                            ]
                        )
            else:
                logger.info("[PERMISSIONS] Opening System Preferences for missing permissions...")
                if not accessibility_ok:
                    subprocess.Popen(
                        [
                            "open",
                            "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility",
                        ]
                    )
                    time.sleep(0.5)
                if not screen_ok:
                    subprocess.Popen(
                        [
                            "open",
                            "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",
                        ]
                    )
                    time.sleep(0.5)
                if not input_monitoring_ok and (
                    major_version > 10 or (major_version == 10 and minor_version >= 15)
                ):
                    subprocess.Popen(
                        [
                            "open",
                            "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent",
                        ]
                    )
            logger.info("[PERMISSIONS] Opened settings for permissions still required.")
        else:
            logger.info("[PERMISSIONS] All checked permissions granted — not opening System Settings.")

        _schedule_login_item_retry(logger)

    except subprocess.TimeoutExpired:
        logger.warning("[PERMISSIONS] Permission dialog timed out")
    except Exception as e:
        logger.error("[PERMISSIONS] Error requesting permissions: %s", e, exc_info=True)


def _schedule_login_item_retry(logger) -> None:
    from ws_package.thread_manager import is_worker_alive, register_worker  # type: ignore

    if is_worker_alive("LoginItemRetry"):
        logger.debug("[LOGIN_ITEM] Login item retry thread already running, skipping")
        return

    def _delayed_login_item_retry():
        time.sleep(3)
        if check_accessibility_permission():
            retry_login_item_setup(logger)
        else:
            logger.info("[LOGIN_ITEM] Accessibility permission not yet granted — will retry when available")

    retry_thread = threading.Thread(target=_delayed_login_item_retry, daemon=True, name="LoginItemRetry")
    retry_thread.start()
    register_worker("LoginItemRetry", retry_thread)


def request_macos_permissions_non_blocking(logger) -> None:
    """
    Run permission prompt flow in background so app bootstrap is not blocked by
    permission probe sleeps/settings navigation.
    """
    if platform.system() != "Darwin":
        return

    def _run_in_background():
        try:
            request_macos_permissions(logger)
        except Exception as e:
            logger.error("[PERMISSIONS] Background permission request failed: %s", e, exc_info=True)

    worker = threading.Thread(
        target=_run_in_background,
        daemon=True,
        name="PermissionPromptWorker",
    )
    worker.start()
    logger.info("[PERMISSIONS] Permission prompt worker started in background")


# ---------------------------------------------------------------------------
# 7. Login item retry
# ---------------------------------------------------------------------------

def retry_login_item_setup(logger) -> bool:
    """
    If Accessibility permission is granted, locate the app bundle and call
    setup_login_item().  Returns True on success.
    """
    if platform.system() != "Darwin":
        return False

    if not check_accessibility_permission():
        logger.debug("[LOGIN_ITEM] Accessibility permission not granted, skipping login item setup")
        return False

    try:
        app_bundle_path = os.path.dirname(os.path.dirname(os.path.dirname(sys.executable)))
        if os.path.exists(app_bundle_path) and app_bundle_path.endswith(".app"):
            logger.info("[LOGIN_ITEM] Retrying login item setup (Accessibility permission available)")
            success = setup_login_item(app_bundle_path, logger)
            if success:
                logger.info("[LOGIN_ITEM] Login item successfully added after permission grant")
            return success
        else:
            logger.warning("[LOGIN_ITEM] Could not find app bundle at %s", app_bundle_path)
            return False
    except Exception as e:
        logger.error("[LOGIN_ITEM] Error retrying login item setup: %s", e)
        return False


# ---------------------------------------------------------------------------
# 8. Login item setup (osascript / System Events)
# ---------------------------------------------------------------------------

def setup_login_item(app_bundle_path: str, logger) -> bool:
    """
    Add *app_bundle_path* as a macOS Login Item via System Events.

    Requires Accessibility permission.  Returns True on success, False on
    failure (never raises).
    """
    try:
        if not os.path.isabs(app_bundle_path):
            app_bundle_path = os.path.abspath(app_bundle_path)

        if not os.path.exists(app_bundle_path):
            logger.error("[ERROR] App bundle not found at: %s", app_bundle_path)
            return False

        if not app_bundle_path.endswith(".app"):
            logger.error("[ERROR] Path does not appear to be an app bundle: %s", app_bundle_path)
            return False

        logger.info("[INFO] Attempting to add Login Item for: %s", app_bundle_path)

        # Remove any existing entry first.
        remove_script = """
        tell application "System Events"
            try
                if exists login item "Workstatus" then
                    delete login item "Workstatus"
                end if
            end try
        end tell
        """
        remove_result = subprocess.run(
            ["osascript", "-e", remove_script],
            capture_output=True, text=True, timeout=5,
        )
        if remove_result.returncode != 0:
            logger.debug("[DEBUG] Remove existing login item result: %s", remove_result.stderr)

        posix_path = app_bundle_path.replace("\\", "/")
        add_script = f"""
        tell application "System Events"
            try
                make login item at end with properties {{path:"{posix_path}", hidden:true, name:"Workstatus"}}
                return true
            on error errorMessage
                return errorMessage
            end try
        end tell
        """
        result = subprocess.run(
            ["osascript", "-e", add_script],
            capture_output=True, text=True, timeout=10,
        )

        error_output = result.stderr.lower() if result.stderr else ""
        stdout_output = result.stdout.lower() if result.stdout else ""

        if result.returncode == 0 and ("true" in stdout_output or result.stdout.strip() == ""):
            logger.info("[SUCCESS] Login Item added successfully — Workstatus will start on login")
            return True

        if "not allowed assistive access" in error_output or "not allowed" in error_output:
            logger.warning("[WARN] Failed to add Login Item: Accessibility permission required")
        elif "system events" in error_output:
            logger.warning("[WARN] Failed to add Login Item: System Events access denied (need Accessibility permission)")
        else:
            logger.warning(
                "[WARN] Failed to add Login Item: %s",
                result.stderr or result.stdout or "Unknown error",
            )
        return False

    except subprocess.TimeoutExpired:
        logger.warning("[WARN] Login Item setup timed out (may need Accessibility permission)")
        return False
    except Exception as e:
        logger.error("[ERROR] Failed to setup Login Item: %s", e)
        return False


# ---------------------------------------------------------------------------
# 9. LaunchAgent setup
# ---------------------------------------------------------------------------

def setup_launchagent_for_autostart(target_dir, workstatus_exec_target, logger) -> bool:
    """
    Write a LaunchAgent plist and register it with launchctl.

    Uses ``launchctl bootstrap`` on macOS 13+ and ``launchctl load`` on older
    versions.  Returns True on success, False on failure (never raises).
    """
    try:
        launchagents_dir = Path.home() / "Library" / "LaunchAgents"
        launchagents_dir.mkdir(parents=True, exist_ok=True)

        plist_file = launchagents_dir / "com.workstatus.engine.plist"

        app_bundle_path = os.path.dirname(os.path.dirname(os.path.dirname(workstatus_exec_target)))

        if not os.path.exists(app_bundle_path) or not app_bundle_path.endswith(".app"):
            logger.error(
                "[ERROR] App bundle not found at %s — cannot create LaunchAgent",
                app_bundle_path,
            )
            return False

        plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.workstatus.engine</string>

    <key>ProgramArguments</key>
    <array>
      <string>/usr/bin/open</string>
      <string>{app_bundle_path}</string>
    </array>

    <key>WorkingDirectory</key>
    <string>{target_dir}</string>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <false/>

    <key>LimitLoadToSessionType</key>
    <string>Aqua</string>

    <key>StandardOutPath</key>
    <string>{target_dir}/launchd_out.log</string>

    <key>StandardErrorPath</key>
    <string>{target_dir}/launchd_err.log</string>

    <key>Nice</key>
    <integer>1</integer>
  </dict>
</plist>"""

        plist_file.write_text(plist_content)
        logger.info("[INFO] Created LaunchAgent plist: %s", plist_file)

        import getpass  # stdlib — inline import keeps module-level imports clean

        macos_version = platform.mac_ver()[0]
        ver_parts = macos_version.split(".")
        major_version = int(ver_parts[0])

        user_id = os.getuid()

        # Bootout any existing agent on macOS 13+.
        if major_version >= 13:
            try:
                subprocess.run(
                    ["launchctl", "bootout", f"gui/{user_id}/com.workstatus.engine"],
                    capture_output=True, text=True, timeout=5,
                )
                logger.info("[INFO] Unloaded existing LaunchAgent (if any)")
            except Exception as e:
                logger.info("[INFO] No existing LaunchAgent to unload: %s", e)

        if major_version >= 13:
            bootstrap_domain = f"gui/{user_id}"
            logger.info("[INFO] Bootstrapping LaunchAgent for macOS %s", major_version)
            result = subprocess.run(
                ["launchctl", "bootstrap", bootstrap_domain, str(plist_file)],
                capture_output=True, text=True,
            )
            if result.returncode != 0:
                if "already bootstrapped" in result.stderr.lower() or result.returncode == 36:
                    logger.info("[INFO] LaunchAgent already bootstrapped — removing and re-adding")
                    subprocess.run(
                        ["launchctl", "bootout", f"gui/{user_id}/com.workstatus.engine"],
                        capture_output=True, text=True, timeout=5,
                    )
                    result = subprocess.run(
                        ["launchctl", "bootstrap", bootstrap_domain, str(plist_file)],
                        capture_output=True, text=True,
                    )
        else:
            logger.info("[INFO] Using legacy launchctl load for macOS %s", major_version)
            result = subprocess.run(
                ["launchctl", "load", str(plist_file)],
                capture_output=True, text=True,
            )

        if result.returncode == 0:
            logger.info("[SUCCESS] LaunchAgent loaded — Workstatus will start automatically on boot")
            return True
        else:
            logger.error("[ERROR] Failed to load LaunchAgent: %s", result.stderr)
            logger.warning("[WARN] LaunchAgent setup failed — app may not auto-start on reboot")
            return False

    except Exception as e:
        logger.error("[ERROR] Failed to setup LaunchAgent: %s", e)
        return False


# ---------------------------------------------------------------------------
# 10. Verify and fix LaunchAgent
# ---------------------------------------------------------------------------

def verify_and_fix_launchagent(logger) -> bool:
    """
    Check whether the LaunchAgent is loaded; bootstrap it if not.

    Uses ``launchctl print`` on macOS 13+ and ``launchctl list`` on older
    versions.  Returns True when the agent is (or becomes) loaded.
    """
    try:
        plist_file = Path.home() / "Library" / "LaunchAgents" / "com.workstatus.engine.plist"

        if not plist_file.exists():
            logger.warning("[AUTOSTART] LaunchAgent plist not found — app may not auto-start on next boot")
            return False

        user_id = os.getuid()
        macos_version = platform.mac_ver()[0]
        major_version = int(macos_version.split(".")[0])

        if major_version >= 13:
            result = subprocess.run(
                ["launchctl", "print", f"gui/{user_id}/com.workstatus.engine"],
                capture_output=True, text=True, timeout=5,
            )
            is_loaded = result.returncode == 0
        else:
            result = subprocess.run(
                ["launchctl", "list", "com.workstatus.engine"],
                capture_output=True, text=True, timeout=5,
            )
            is_loaded = result.returncode == 0 and "com.workstatus.engine" in result.stdout

        if is_loaded:
            logger.debug("[AUTOSTART] LaunchAgent is already loaded — auto-start is active")
            return True

        logger.info("[AUTOSTART] LaunchAgent not loaded — bootstrapping to ensure auto-start on next boot...")

        if major_version >= 13:
            bootstrap_result = subprocess.run(
                ["launchctl", "bootstrap", f"gui/{user_id}", str(plist_file)],
                capture_output=True, text=True, timeout=10,
            )
            if bootstrap_result.returncode == 0:
                logger.info("[AUTOSTART] LaunchAgent bootstrapped successfully")
                return True
            if "already bootstrapped" in bootstrap_result.stderr.lower() or bootstrap_result.returncode == 36:
                logger.info("[AUTOSTART] LaunchAgent already bootstrapped")
                return True
            logger.warning("[AUTOSTART] Failed to bootstrap LaunchAgent: %s", bootstrap_result.stderr)
            return False
        else:
            load_result = subprocess.run(
                ["launchctl", "load", str(plist_file)],
                capture_output=True, text=True, timeout=10,
            )
            if load_result.returncode == 0:
                logger.info("[AUTOSTART] LaunchAgent loaded successfully")
                return True
            logger.warning("[AUTOSTART] Failed to load LaunchAgent: %s", load_result.stderr)
            return False

    except Exception as e:
        logger.warning("[AUTOSTART] Error verifying LaunchAgent: %s", e)
        return False


# ---------------------------------------------------------------------------
# 11. Permission monitor
# ---------------------------------------------------------------------------

def start_permission_monitor(logger) -> None:
    """
    Start a background daemon thread that monitors Screen Recording and
    Accessibility permissions.

    - Checks every 60 s while any permission is missing; drops to every 300 s
      once both are granted.
    - Respects a 60 s grace period after a system wake event.
    - When Accessibility transitions False → True (after 3 confirmations) it
      calls retry_login_item_setup().
    - Audio input is NOT monitored here: check_audio_input_permission() always
      returns True and there is nothing meaningful to track.
    - show_restart_prompt() was dead code and has been removed.
    """
    global _permission_monitor_started

    if platform.system() != "Darwin":
        return

    if _permission_monitor_started:
        logger.debug("[PERMISSIONS] Permission monitor already started")
        return

    def _monitor():
        logger.info("[PERMISSIONS] Starting permission monitor thread...")

        last_screen_recording = False
        last_accessibility = False

        screen_recording_confirm_count = 0
        accessibility_confirm_count = 0
        required_confirmations = 3

        last_wake_time = None
        wake_grace_period = 60  # seconds

        # Allow the app to finish starting before the first check.
        time.sleep(5)

        last_screen_recording = check_screen_recording_permission(logger)
        last_accessibility = check_accessibility_permission()

        logger.info(
            "[PERMISSIONS] Initial state — Screen Recording: %s, Accessibility: %s",
            last_screen_recording, last_accessibility,
        )

        if last_accessibility:
            retry_login_item_setup(logger)

        # Register wake callback to avoid false permission-revoke detections.
        try:
            from ws_package.utils.system_wake_detector import get_system_wake_detector  # type: ignore

            wake_detector = get_system_wake_detector()
            if wake_detector:
                def _on_wake():
                    nonlocal last_wake_time
                    last_wake_time = time.time()
                    logger.debug("[PERMISSIONS] Wake event detected — entering grace period")

                wake_detector.register_wake_callback("permission_monitor", _on_wake)
        except Exception as e:
            logger.debug("[PERMISSIONS] Could not register wake callback: %s", e)

        check_interval = 60          # seconds when any permission is missing
        granted_check_interval = 300  # seconds when all permissions are granted

        while True:
            try:
                if last_screen_recording and last_accessibility:
                    time.sleep(granted_check_interval)
                else:
                    time.sleep(check_interval)

                if last_wake_time and (time.time() - last_wake_time) < wake_grace_period:
                    logger.debug("[PERMISSIONS] In wake grace period — skipping permission check")
                    continue

                current_screen_recording = check_screen_recording_permission(logger)
                current_accessibility = check_accessibility_permission()

                # --- Accessibility ---
                if not last_accessibility and current_accessibility:
                    accessibility_confirm_count += 1
                    if accessibility_confirm_count >= required_confirmations:
                        logger.info("[PERMISSIONS] Accessibility permission granted (confirmed)")
                        last_accessibility = True
                        accessibility_confirm_count = 0
                        retry_login_item_setup(logger)
                    else:
                        logger.debug(
                            "[PERMISSIONS] Accessibility positive check %d/%d",
                            accessibility_confirm_count, required_confirmations,
                        )
                elif last_accessibility and not current_accessibility:
                    logger.warning("[PERMISSIONS] Accessibility permission revoked")
                    last_accessibility = False
                    accessibility_confirm_count = 0
                else:
                    accessibility_confirm_count = 0

                # --- Screen Recording ---
                if not last_screen_recording and current_screen_recording:
                    screen_recording_confirm_count += 1
                    if screen_recording_confirm_count >= required_confirmations:
                        logger.info("[PERMISSIONS] Screen Recording permission granted (confirmed)")
                        last_screen_recording = True
                        screen_recording_confirm_count = 0
                    else:
                        logger.debug(
                            "[PERMISSIONS] Screen Recording positive check %d/%d",
                            screen_recording_confirm_count, required_confirmations,
                        )
                elif last_screen_recording and not current_screen_recording:
                    logger.warning("[PERMISSIONS] Screen Recording permission revoked")
                    last_screen_recording = False
                    screen_recording_confirm_count = 0
                else:
                    screen_recording_confirm_count = 0

            except Exception as e:
                logger.error("[PERMISSIONS] Error in permission monitor: %s", e, exc_info=True)
                time.sleep(30)

    monitor_thread = threading.Thread(target=_monitor, daemon=True, name="PermissionMonitor")
    monitor_thread.start()
    _permission_monitor_started = True
    logger.info("[PERMISSIONS] Permission monitor thread started")


# ---------------------------------------------------------------------------
# 12. Silent mode user token (MDM / first-install)
# ---------------------------------------------------------------------------

_TOKEN_FILE = "user_token_file.txt"


def _find_token_file_src_mac(exe_dir: Path, app_bundle_path: Path) -> Path | None:
    """Locate user_token_file.txt beside the bundle or common MDM drop locations."""
    candidates = (
        exe_dir / _TOKEN_FILE,
        app_bundle_path.parent / _TOKEN_FILE,
        app_bundle_path / _TOKEN_FILE,
        exe_dir / "upgrade" / _TOKEN_FILE,
        Path.cwd() / _TOKEN_FILE,
        Path.home() / "Downloads" / _TOKEN_FILE,
        Path.home() / "Desktop" / _TOKEN_FILE,
    )
    for candidate in candidates:
        try:
            if candidate.is_file():
                return candidate.resolve()
        except OSError:
            continue
    return None


def _copy_token_file_to_app_support(target_dir: Path, token_src: Path, logger) -> None:
    token_target = target_dir / _TOKEN_FILE
    shutil.copy2(token_src, token_target)
    token_target.chmod(stat.S_IRUSR | stat.S_IWUSR)
    logger.info("[Silent] Copied user_token_file.txt to %s", token_target)


def _ensure_silent_user_token_mac(
    exe_dir: Path,
    app_bundle_path: Path,
    target_dir: Path,
    logger,
) -> None:
    """
    Silent builds: ensure user_token_file.txt lives in Application Support.

    MDM may place the token next to the .app, inside Contents/MacOS, in an
    upgrade/ folder, or in Downloads/Desktop — copy it on first install.
    """
    try:
        from ws_package.utils.build_mode import is_silent_build
    except Exception:
        return
    if not is_silent_build():
        return

    target_dir.mkdir(parents=True, exist_ok=True)
    token_target = target_dir / _TOKEN_FILE
    if token_target.is_file():
        logger.debug("[Silent] user_token_file.txt already present: %s", token_target)
        return

    token_src = _find_token_file_src_mac(exe_dir, app_bundle_path)
    if not token_src:
        logger.warning(
            "[Silent] user_token_file.txt not found beside %s, in cwd, or Downloads — "
            "place it in %s for stealth_login",
            app_bundle_path,
            target_dir,
        )
        return

    try:
        _copy_token_file_to_app_support(target_dir, token_src, logger)
    except OSError as exc:
        logger.error(
            "[Silent] Failed to copy user_token_file.txt to Application Support: %s",
            exc,
        )


# ---------------------------------------------------------------------------
# 13. Main macOS setup entry point
# ---------------------------------------------------------------------------

def setup_macos(logger) -> bool:
    """
    macOS-specific startup setup.

    When the frozen app is **not** yet in Application Support:
      1. Copy the app bundle there (ditto preferred, shutil fallback).
      2. Strip quarantine/provenance xattrs.
      3. Launch the copy and sys.exit(0) so the installer hands off cleanly.

    When the app **is** already running from Application Support:
      1. Set up a LaunchAgent for autostart.
      2. Fall back to a Login Item if the LaunchAgent fails.
      3. Return True so the caller can continue with normal startup.

    This function is a no-op (returns True) if not running as a frozen macOS app.
    """
    if not (getattr(sys, "frozen", False) and platform.system() == "Darwin"):
        return True

    # Inline ExitCode / ErrorCode constants to avoid coupling to ws_engine globals.
    # These must match the values used in ws_engine.py.
    try:
        from ws_package.exit_codes import ExitCode, ErrorCode  # type: ignore
        exit_ok = ExitCode.OK
        log_handoff = lambda: logger.critical("%s", ErrorCode.SETUP_MAC_HANDOFF)
    except Exception:
        exit_ok = 0
        log_handoff = lambda: logger.critical("[SETUP] Handing off to Application Support copy")

    exe_dir = Path(sys.executable).parent          # …/Workstatus.app/Contents/MacOS
    app_bundle_path = exe_dir.parent.parent        # …/Workstatus.app
    target_dir = CANONICAL_APP_SUPPORT
    target_app = CANONICAL_APP_BUNDLE

    logger.info("[INFO] App bundle location: %s", app_bundle_path)
    logger.info("[INFO] Executable location: %s", sys.executable)

    try:
        if not target_app.exists() or app_bundle_path.resolve() != target_app.resolve():
            logger.info("[INFO] Ensuring Application Support install...")
            target_dir.mkdir(parents=True, exist_ok=True)

            if target_app.exists():
                shutil.rmtree(target_app)

            copy_started = time.time()
            try:
                result = subprocess.run(
                    ["ditto", str(app_bundle_path), str(target_app)],
                    capture_output=True, text=True,
                )
                if result.returncode != 0:
                    logger.warning("[INFO] ditto failed, falling back to Python copy: %s", result.stderr.strip())
                    shutil.copytree(app_bundle_path, target_app)
            except Exception as e:
                logger.warning("[INFO] ditto not available or failed: %s — falling back to Python copy", e)
                shutil.copytree(app_bundle_path, target_app)
            finally:
                logger.info(
                    "[INFO] Application Support copy completed in %d ms",
                    int((time.time() - copy_started) * 1000),
                )

            # Strip quarantine and provenance attributes.
            subprocess.run(["xattr", "-rd", "com.apple.quarantine", str(target_app)], check=False, capture_output=True)
            subprocess.run(["xattr", "-rd", "com.apple.provenance", str(target_app)], check=False, capture_output=True)

            invalidate_screen_recording_cache(logger)
            try:
                BUNDLE_IDENTITY_MARKER.unlink(missing_ok=True)
            except OSError:
                pass

            # Allow forced re-stapling via env (skip in dev builds to save time).
            if os.environ.get("FORCE_STAPLE", "") == "1":
                subprocess.run(["xcrun", "stapler", "staple", str(target_app)], check=False, capture_output=True)

            _ensure_silent_user_token_mac(exe_dir, app_bundle_path, target_dir, logger)

            # Relaunch from Application Support and exit.
            target_exe = target_app / "Contents" / "MacOS" / "Workstatus"
            if target_exe.exists():
                subprocess.Popen(
                    [str(target_exe)],
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
                log_handoff()
                sys.exit(exit_ok)
            else:
                logger.error("[ERROR] Could not find executable in Application Support — continuing from current location")
        else:
            logger.info("[INFO] Already running from Application Support location")
            _ensure_silent_user_token_mac(exe_dir, app_bundle_path, target_dir, logger)

    except Exception as e:
        logger.error("[ERROR] Application Support install error: %s", e)
        logger.info("[INFO] Continuing from current location...")

    # Already in Application Support — set up autostart.
    launchagent_success = setup_launchagent_for_autostart(target_dir, sys.executable, logger)
    if launchagent_success:
        time.sleep(2)
        if verify_and_fix_launchagent(logger):
            logger.info("[SUCCESS] LaunchAgent setup completed and verified")
        else:
            logger.warning("[WARN] LaunchAgent setup may have failed — check logs")
    else:
        logger.error("[ERROR] Failed to setup LaunchAgent")

    # Login Item as fallback / backup.
    bundle_path = os.path.dirname(os.path.dirname(os.path.dirname(sys.executable)))
    if os.path.exists(bundle_path) and bundle_path.endswith(".app"):
        login_item_success = setup_login_item(bundle_path, logger)
        if login_item_success:
            logger.info("[SUCCESS] Login Item setup completed")
        elif not launchagent_success:
            logger.warning("[WARN] Both LaunchAgent and Login Item setup failed — app may not auto-start on restart")
    else:
        logger.warning("[WARN] Could not find app bundle at %s for Login Item setup", bundle_path)

    logger.info("[INFO] macOS setup complete. Running from current location.")
    return True
